BEYOND SW 캠프 15기 6주차 회고

mijuckboon·2025년 3월 1일
post-thumbnail

2월에서 3월로 넘어가는 시점이기도 한 6주차를 돌아보며 회고를 작성해본다.

학습 내용

  1. 다형성
    객체 지향의 4대 특징(캡슐화, 상속, 다형성, 추상화) 중 하나인 다형성의 개념에 대해 배우고, 자주 import하여 사용하는 Java 패키지에 다형성이 어떻게 적용되어 있는지를 알아보았다.
  2. 클래스, 인터페이스
    Java의 클래스, 인터페이스의 개념 및 자주 사용하는 API의 활용법을 배웠다.
  3. 예외 처리, 입출력, 스트림
    예외처리 문법과 표준 입출력, 파일 입출력, 스트림의 개념을 배우고 실습하였다.

배운 점

이번주 학습을 통해 배운 내용을 정리해본다.

1. 클래스

클래스는 SQL에서의 테이블과 비슷한 점도 많지만, 백엔드 코드에서는 자료형의 역할을 하기도 하고 객체 생성 방식을 지정해주기도 하는 독특한 개념이다.
실습 문제를 통해 "도형" 클래스를 상속받는 "원", "직사각형", "삼각형" 등의 클래스를 구현해보며, 이전 직장에서 자주 사용되는 대상을 Python 클래스로 만들어 관리했던 것이 생각났다. 특히 이 중에서도 삼각형 클래스를 완성해보는 것은 좋은 공부가 될 것 같다.

  1. 인스턴스 변수: 세 변의 길이, 세 각의 크기를 인스턴스 변수로 관리한다.
public class Triangle {
	// 인스턴스 변수
  private double sideA; // 변 BC (길이 a)
  private double sideB; // 변 AC (길이 b)
  private double sideC; // 변 AB (길이 c)
  private double angleA;
  private double angleB;
  private double angleC;
 }
  1. 생성자: 삼각형은 다음 중 하나가 정해지면 유일하게 결정된다. (삼각형의 합동 조건 SSS, SAS, ASA를 떠올리면 된다.)
  1. 세 변의 길이
  2. 두 변의 길이와 끼인각의 크기
  3. 한 변의 길이와 양쪽 각의 크기

따라서 위의 3가지 방법으로 생성할 수 있도록 3개의 생성자를 정의해주면 된다. 만약 필요에 따라 다른 생성자(예시: 세 변과 세 각의 크기를 모두 입력받음)도 추가한다면, 그게 유효한 삼각형인지 검증을 거쳐야 한다. 예를 들어 sideA = 3, sideB = 4, sideC = 5, angleA=30인 삼각형은 존재할 수 없으므로 이런 객체의 생성은 막아야 한다.

// SSS 생성자
public Triangle(double sideA, double sideB, double sideC) {
	this.sideA = sideA;
    this.sideB = sideB;
    this.sideC = sideC;
    // 이하 생략
}

// SAS 생성자
public Triangle(double sideA, double sideB, double angleC) {
	// 생략
}

// ASA 생성자 (이하 생략)
  1. 검증 로직
    위에 언급한 경우 외에도 추가로 검증을 거쳐야 하는게 하나 더 있다. 세 변의 길이가 2, 3, 5인 삼각형, 세 변의 길이가 2, 3, 6인 삼각형은 존재하지 않으므로 이런 객체의 생성 또한 막아야 한다.

  2. 메서드 정의
    경우에 따라 필요한 내용(둘레, 넓이 등)을 계산할 수 있도록 메서드를 정의한다.

위와 같이 도형을 코드로 관리하는 것은 꽤나 복잡하기 때문에, 자주 써야한다면 관련 로직을 미리 클래스에 정의해두고 불러오는 것이 좋다고 생각한다. 이렇게 클래스를 작성해보는 게 많은 공부가 될 것 같아, 시간이 허락할 때 조금씩 채우며 완성해볼까 한다.

2. 개행 문자의 동작 방식

파일 입출력 처리에 대한 수업 중 파일을 입력받아 저장한 char[] 배열을 출력하는 내용을 다루었는데, toString() 메서드를 이용하니 예상과 다른 출력 결과가 나와서 for 문을 이용하는 것으로 코드가 수정되었다.

  • 입력한 파일 (txt)
안녕하세요.
반갑습니다.
저는 홍길동입니다.
  • 작성된 코드
try (FileReader fr = new FileReader("testReader.txt")) {
            char[] carr = new char[100];
            fr.read(carr);
            System.out.println(Arrays.toString(carr));
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
  • 실행 결과
    예상치 못한 결과

이 현상을 보며 다음의 2가지 가설을 세우고 실험해보았다.
1. 한글을 제대로 처리하지 못해서 발생한 문제이다.
2. 개행 문자를 제대로 처리하지 못해서 발생한 문제이다.

실험 결과 2번에 언급한 대로 개행 문자를 제대로 처리하지 못해 발생한 문제였다. 엔터를 없애고 "안녕하세요."만 남겼더니 아래와 같이 예상대로 잘 출력되었다.
개행 제거 후 실행 결과

이 결과를 강사님께 공유드렸더니 \r\n <- 개행 문자가 콘솔에서 기능할 때 앞에 내용을 덮어쓰기 해버힌다.라고 말씀해주셨다. "덮어쓴다"라는 이야기에서 문득

이스케이프 코드에 대한 내용을 찾아보면 흔히 캐리지 리턴(\r, Carriage Return, CR)이 커서를 맨 앞으로 옮긴다.라고 하는데 혹시 이와 관련이 있을까?

싶어서 개행 방식을 바꾸며 실험해보았다. 내용을 잘 확인하기 위해 carr은 길이 30인 배열로 수정하였다.

  • 실험 결과
    실험 결과

Arrays.toString()을 이용해 출력할 때의 결과가 왜 위와 같은 지 간략히 설명해본다. 입력한 텍스트 파일은 다음과 같이 처리된다.

  1. CRLF (CR+LF, Windows)
12345678910
.\r\n
.\r\n
.

□는 가시성을 위해 아스키 코드 0에 대응되는 NUL 문자의 의미로 사용했다. (오타가 아니다! 하단 참고용 이미지 출처: https://www.ascii-code.com/)
아스키 코드표

Array 형태로 출력하려다가 \r을 만나면 커서가 맨 앞으로 이동한 뒤 덮어쓰기를 진행하여, 위의 실험 결과와 같이 이상하게 출력된 것이다.

  1. LF (Line Feed, Unix 및 Mac OS)
12345678910
.\n
.\n
.

\n에서 개행만 수행되므로 예상대로 잘 출력된다. \r\n\n으로 바뀌었으므로 빈 칸이 2개 증가한 것도 확인할 수 있다.

  1. CR (Carriage Return, Classic Mac OS)

\r을 만나면 덮어쓰기 되므로 Array를 이용한 출력 및 for 문을 이용한 출력 모두에서 예상치 못한 결과를 출력한다.

이렇게 파일 입출력 스트림을 통해 확인해보니 이스케이프 코드의 의미를 잘 이해할 수 있었다.

3. SQL의 중요성

스트림 단원의 실습 문제는 스트림을 이용하여 원하는 조건에 맞는 결과를 출력하는 코드를 작성하는 것이었다. 스트림 연산은 결과를 되돌릴 수 없기에 알맞은 순서에 따라 작성하는 것이 중요했는데, 그 때 SQL에서 배운 SELECT 문의 처리 순서를 떠올려본 게 도움되었다.

// 2. IT 부서에서 급여가 5,000 이상인 직원의 이름을 급여 순으로 내림차순 정렬하여 반환
        List<String> highSalaryIT = employees.stream() // from
                .filter(x -> x.getSalary() >= 5000) // where
                .sorted((x, y) -> y.getSalary() - x.getSalary()) // order by
                .map(Employee::getName) // select
                .collect(Collectors.toList());

급여 정보를 통해 먼저 정렬하고 이름을 반환하는 점에서 약간의 차이는 있지만 SQL에서 배운 순서와 꽤 흡사하다.

SELECT 문 동작 순서
FROMWHEREGROUP BYHAVINGSELECTORDER BY

Java 스트림 실습과 SQL 학습 내용이 이렇게 연결될 줄은 몰랐는데, 당시에 공부를 잘 해둔 덕을 봤다. 다시 만나게 되어 반가웠다.

4. API 활용

지난 회고에서 언급했던 로또 추첨 문제의 경우, TreeSet 클래스를 활용하면 매우 간단하게 구현할 수 있다는 사실을 배웠다.

Set<Integer> lotto = new TreeSet<>();
        while (lotto.size() < 6) {
            lotto.add((int) (Math.random() * 45) + 1);
        }
        System.out.println("lotto : " + lotto);

중복을 허용하지 않고 숫자를 추첨하는 로직을 직접 작성해보는 것은 알고리즘 공부 측면에서 좋은 소재이지만, 이런 로직을 직접 작성하는 것보다는 이미 다른 사람들이 만들어 놓은 도구를 잘 활용할 줄 아는 능력이 실무에서는 더 중요할 것이다. import한 패키지의 수정 사항으로 인해 기존에 작성한 코드를 수습해야 하는 경우가 생길 수도 있지만, Collection 프레임워크는 비교적 이런 위험성이 낮은 안정적인 도구일 것이다. 이런 안정적인 API를 적절히 활용하여, 간단하게 문제를 해결하는 방법을 잘 익혀두는 것이 좋겠다.

문제 상황

이번 주에 겪었던 문제 상황을 공유해본다.

Application 클래스가 사용되지 않는다는 경고가 뜨는 문제

문제 상황

  • 설명: 위와 같이 Application1 클래스 내부에 메시지를 관리하기 위한 enum 클래스를 정의하여 코드를 작성했는데, 위의 사진과 같이 Application1 클래스는 회색으로 표시되었다. 또, 클래스 'Application1'이(가) 한 번도 사용되지 않습니다라는 메시지가 떴다. 다른 Application 클래스에서는 발생하지 않았던 현상이기에, 혹시 내부에 enum 클래스를 정의한 게 원인인가 싶었다.

  • 해결 방법: 나중에 집에 가서 열어봤더니 메시지가 사라짐
    내부에 enum 클래스를 정의한 것은 원인이 아니었다. 저번 주 회고에서 언급한 문제 상황과 마찬가지로 캐시가 깨진 것이 원인으로 보인다. 역시 예상치 못한 현상이 발생했을 때 프로그램 또는 기계를 껐다가 켜보는 것은 허무하지만 잘 통하는 해결법인가보다.

개선할 점

이번주는 집에 돌아오면 유독 피곤해서 평소보다 일찍 잠들었다. 백준 클래스 2 문제를 2주 안에 푸는 게 목표였는데, 시간을 많이 투자하지 못해 지금의 페이스로는 목표 달성이 어려운 상태이다. 마침 다음 주 월요일도 휴일이라 남은 시간이 많으니, 2주 안에 끝낼 수 있게 휴일동안 백준을 달려야겠다.

느낀 점

영광스럽게도 필자의 지난 주 회고가 우수 회고로 선정되었다.
매니저님 채팅
사실 정확한 이유는 지금도 잘 모르겠지만, 지금까지의 6주를 돌이켜봤을 때 가장 회고를 쓰기 싫었던 게 바로 저번 주였다. 원래 토요일 낮에 쓰려고 했던 걸 미루다가 그날 밤이 되어서야 작성하기 시작했는데, 하기 싫음을 견디고 완성해낸 것에 대한 보상을 받은 것 같아 정말 기뻤다. 회고 블로그를 개설하기 전에 어떤 글을 쓰다가 시간이 너무 오래 걸려서 그냥 그만 둘까하는 생각을 한 적이 몇 번 있었는데, 결과적으로 그 때 끝까지 글을 완성해본 경험들이 회고 작성에 많은 도움이 되었다.
때로는 어떤 일을 하기 싫거나 그만 두고 싶은 순간이 오기도 하는데, 이를 이겨내고 끝까지 해보는 것이 중요하다는 생각이 든다. (물론 정말 그만둬야 하는 상황에서는 그만 둘 줄 아는 용기도 필요하다.)
앞으로도 무언가를 하기 싫다는 생각이 들 때, 이번 우수 회고 선정을 기억하며 끝까지 최선을 다해봐야겠다.

profile
곽진웅, 백엔드 개발자 준비 중

5개의 댓글

comment-user-thumbnail
2025년 3월 3일

와! 회고 퀄리티가 점점 더 발전하네요. 문제에 대한 접근 방법과 해결 과정이 과연 수학 전공자답다는 생각이 듭니다. 공부 잘하는 친구 노트 빌려 보는 기분으로 매주 방문하고 있는데 많은 도움이 되고 있습니다. 항상 감사하고, 우수 회고 축하드립니다!

1개의 답글
comment-user-thumbnail
2025년 3월 4일

오우 ㅋ 지금처럼 꾸준히 쓰시면 수료후에 개인 블로그 작성하는 습관이라는 큰 자산을 얻어가실 겁니다 ! 홧팅!

답글 달기
comment-user-thumbnail
2025년 4월 2일

우와 스트림 연산 구조가 SELECT문 동작 순서와 유사하군요 신기하네요 ㅎㅎ 진웅님 블로그에 흥미로운 분석이 많아서 유익하고 재미있어용 6주차부터 최근 포스트까지 쭉 읽으러 왔어요 파이팅입니다~

1개의 답글