이번 주는 3.1절 연휴로 인해서 화~목만 공부했는데, 체감상 일주일이 1.5배는 빠르게 흘러간 느낌이었다.
3/5에는 Java로 다시 도전하는 PCCE, 3/8는 SQLD 시험이 있었는데, 갑자기 자바를 활용하여 간단한 시스템을 만들어보는 프로젝트도 금요일까지 제출하게 되어서 조금 심적으로 여유가 없었던 주인 것 같다.
어찌저찌 잘 마무리하여 회고를 하고 있기는 하지만 , 체력을 아직 온전히 회복하지 못해서 다음주가 좀 힘들어질지도 모르겠다..
곧 아마 백엔드 프로젝트를 위한 조로 바뀌고, Spring 프레임워크에 대한 학습을 본격적으로 해나갈텐데 컨디션 관리를 잘해서 놓치는 부분없이 잘 흡수하고 싶다.
[수업 내용]
이번주에는 객체 지향 설계의 5대 원칙인 SOLID, JUnit 테스팅, 프레임워크, 23가지에 달하는 디자인 패턴을 가볍게 훑고,
자료 구조(리스트, 스택, 큐, 덱, 트리, 힙)에 대해 학습하고 이를 적용하여 백준 문제를 풀어보았다.
[SOLID 원칙]
-유지보수성, 확장성이 좋은 코드를 작성하기 위한 원칙들
-응집도는 높이고, 결합도는 낮추는 방향으로 설계
SRP(Single Responsibility Principle) - 단일 책임의 원칙
- 하나의 클래스는 단일 책임(기능)을 지녀야 한다는 원칙
- 클래스가 변경되어야 이유는 하나여야 함
-> 여러 가지 기능을 하나의 클래스에서 정의하기보단 각각의 클래스로 분리
-OCP(Open Closed Principle) - 개방 폐쇄의 원칙
- 소프트웨어 요소(클래스, 모듈, 함수)는 확장에는 열려있고 수정에는 닫혀있어야 함
-> 인터페이스를 통해 메소드를 정의하고, 각각의 로직에 따라 다른 클래스에서 해당 메소드를 구현하고 실행 클래스에서 해당 인터페이스를 상속받는 객체를 생성자 파라미터 등으로 주입받음(DI)
-LSP(Liskov Substitution Principle) - 리스코프 치환 원칙
- 프로그램에서 하위 클래스가 상위 클래스를 완전히 대체할 수 있어야 함
- 하위 클래스가 부모 클래스의 기능을 변경하거나 제거해서는 안됨
-> 부모 클래스를 상속받은 하위 클래스의 메서드가 부모 클래스의 메서드와 다른 역할을 수행하지 않도록 함
-ISP(Interface Segregation Principle) - 인터페이스 분리 원칙
- 클라이언트가 자신이 사용하지 않는 인터페이스에 의존하지 않아야 함
- 하나의 인터페이스가 너무 많은 기능을 제공할 시 상속받는 클래스가 기능상 필요없는 메소드까지 구현해야 하는 문제가 발생
-> 인터페이스를 잘게 나누어 필요한 기능만을 담도록 함
-DIP(Dependency Inversion Principle) - 의존 역전 원칙
- 상위 모듈이 하위 모듈에 의존하는 것이 아니라 둘 다 추상화(인터페이스)에 의존해야 함
- 클래스간 결합도를 낮추고 유연성을 높일 수 있음
- 상위 모듈은 비즈니스 로직, 하위 모듈은 구체적 기능, 데이터베이스 crud, 파일 입출력 등이 예시임
-> 상위 모듈에서 하위 모듈을 직접적으로 사용하는 형태가 되면, 하위 모듈을 수정함에 따라 상위 모듈에도 수정이 필요하게 됨. 따라서 인터페이스를 통해 호출 시점에 의존성을 주입
[JUnit]
-애노테이션 종류
- @Test - 테스트 메서드임을 나타냄
- @BeforeEach - 각 테스트 전에 실행되는 메서드를 지정
- @AfterEach - 각 테스트 후에 실행되는 메서드를
- @BeforeAll - 클래스의 모든 테스트 전에 한 번 실행되는 메서드를 지정
- @AfterAll - 클래스의 모든 테스트 후에 한 번 실행되는 메서드를 지정
- @DisplayName - 테스트 클래스나 메서드의 이름을 지정
- @RepeatedTest(int count) - 동일한 테스트를 여러 번 반복 실행할 때 사용

BeforeAll, AfterAll 메소드는 static이어야 함(객체 생성 이전에 이루어지는 행위)

테스트 코드 1 메소드, 테스트 코드 2 메소드를 모두 실행한 결과
before all - (before each - 메소드 동작 - after each) * 메소드 개수 - after all의 순으로 동작
추가적인 사항으로
-@Disabled를 통해 해당 메소드 테스트 비활성화
-@Timeout(value, unit(시간 단위))를 통해 제한 시간 설정
-@RepeatedTest(횟수)를 통해 특정 메소드 여러 번 테스트 반복
-각각의 메소드에 @Order()를 통해 우선순위 지정하고, 클래스 레벨에 @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 선언하면 순서 지정할 수 있음
-어설션
- assertEquals(expected, actual) - 두 값이 같은지 확인, 뒤에 delta 지정하면 해당 값만큼 차이나도 pass시킴
- assertTrue(condition) - 조건이 참인지 확인
- assertFalse(condition) - 조건이 거짓인지 확인
- assertNotNull(object) - 객체가 null이 아닌지 확인
- assertNull(object) - 객체가 null인지 확인
- assertAll() - 여러 개의 Assertion을 한 번에 실행
- assertThrows() - 해당 타입의 Exception을 throw하는지 확인
-AssertJ 라이브러리 더 직관적이고 다양한 Assertion 메서드를 제공하여, 테스트 코드를 더욱 명확하고 간결하게 작성할 수 있음




[복잡도]
- 시간 복잡도 표기법
- Big-O : 최악의 경우를 산정하여 분석
- Big-오메가 : 최선의 경우를 산정하여 분석
- Big-세타 : 위 두 경우의 평균을 산정하여 분석
- 시간 복잡도 종류

-공간 복잡도
- 공간 복잡도-총 공간 요구 = 고정 공간 요구 + 가변 공간 요구-가변 공간 요구(알고리즘과 밀접한 공간)
- -고정 공간(알고리즘과 무관하게 요구되는 공간), 선언된 변수, 배열
- -로직 연산에 사용되는 메모리 공간
[자료구조]
필기한 부분을 모두 가져오기엔 너무 많아서 각 자료형별로 핵심적이라고 생각되는 부분만 정리해보려고 한다.
- 리스트(List)
- 순서가 있는 데이터의 집합으로, 인덱스나 포인터로 접근할 수 있는 자료구조
- 배열 기반의 ArrayList의 경우 인덱스를 이용해 O(1)로 접근할 수 있고, 연속된 메모리 공간을 사용하므로 캐시 히트율이 높다. 그러나 크기를 늘리려면 새로운 배열을 할당해야 하며, 중간 데이터 삽입이나 삭제가 느리다
- LinkedList의 경우 동적으로 노드를 추가/삭제 할 수 있어 메모리를 효율적으로 사용할 수 있으며, 탐색이 느린 대신, 삽입과 삭제가 빠르다. 각 노드에 포인터라는 추가적인 정보가 관리되어야 하므로 메모리 오버헤드가 발생한다.
- 스택(Stack)
- LIFO(Last In, First Out)
- 큐(Queue)
- FIFO(First In, First Out)
- 주로 구현체로 LinkedList를 활용
- 덱(Deque)
- 양쪽 끝에서 삽입과 삭제를 허용하는 자료구조
- 주로 구현체로 ArrayDeque를 활용
- 트리(Tree)

- 계층적인 구조로 노드와 자식 노드들로 구성된 자료구조
- 트리는 정점(node)과 간선(edge)으로 연결된 그래프의 특수한 형태
- 사이클이 없고, 모든 노드들이 연결되어 있어야 하며, 루트 노드를 제외한 노드들은 모두 1개의 부모 노드를 가짐
- 이진 트리
- 트리 중 각 노드가 최대 2개의 자식 노드를 가짐
-트리 순회 방식 3가지

- 전위 순회(Preorder) - 트리를 복사하거나, 전위 표기법을 구하는데 사용
- Root - 왼쪽 서브 트리 전위 순회 - 오른쪽 서브트리 전위 순회
- 중위 순회(Inorder) - 이진 탐색트리(BST)에서 오름차순 혹은 내림차순으로 값을 가져올 때
- 왼쪽 서브 트리 중위 순회 - Root - 오른쪽 서브트리 중위 순회
- 후위 순회(Postorder) - 트리를 삭제할 때 주로 사용
- 왼쪽 서브 트리 후위 순회 - 오른쪽 서브트리 후위 순회- Root
- 힙(Heap)
- 완전 이진 트리 구조를 가지며, 우선 순위 큐를 구현하기 위한 자료구조
- 부모 노드와 자식 노드 사이의 우선순위 관계만 보장
- Java에서는 주로 PriorityQueue를 활용하게 됨
[PCCE]
세부적인 문법을 전혀 외우지 못한 Java로 시험을 봤는데,
저번 PCCE에 비해 난이도가 훨씬 쉬웠던 것 같다.

마지막 9, 10번 구현 중에 뭔가 엣지 케이스에 걸려서 감점이 이루어진 것 같긴 한데
거의 만점에 가까운 점수를 받을 수 있었다.
곧 PCCP 인증시험도 다가오고 있는데, c++로 응시한 만큼 하루에 한 문제라도 실버 상위 ~ 골드 하위 문제를 풀어서 감을 익혀야겠다.
[SQLD]
시험 전날 자바 프로젝트 마무리로 인하여 잠을 3시간정도밖에 자지 못한 상태여서, 공부를 엄청 많이 하진 못했다.
그래도 책을 한번 1회독했던 것들이 남아있었는지, 딱히 아예 모르는 내용은 나오지 않았던 것 같다.
중간중간에 조금 복잡하게 SQL 구문이 작성된 것들이 보기로 주어지고 동작이 다른 1개를 고르는 문제가 제일 오래 걸렸던 것 같다. 나머진 그렇게 어려운 부분이 없었다.
유일하게 아예 몰랐던 문법이 KEEP절이었다.
chatgpt에게 물어보니 group에서 정렬된 기준에 대해 첫 번째 값만을 선택할 수 있도록 한다고 한다.
정렬 기준이 desc였는지 그냥 오름차순이었는지가 기억이 안나서 맞았는지는 기억이 잘 안나는데..
왠지 느낌상 내가 찍은 답이 맞는 것 같긴 하다.
[자바 프로젝트 - Mini BOJ]
https://github.com/splguyjr/Mini-BOJ
GitHub - splguyjr/Mini-BOJ: 자바만을 이용하여 구현한 백준과 같은 회원, 채점 시스템
자바만을 이용하여 구현한 백준과 같은 회원, 채점 시스템. Contribute to splguyjr/Mini-BOJ development by creating an account on GitHub.
github.com
파일 입출력을 기반으로 입력받은 코드를 컴파일하고 테스트 케이스를 입력으로 넣어서 실행한 결과와
기존에 등록해둔 정답 케이스를 비교하여 채점하는 로직의 시스템을 만들었다.
SRP, OCP, ISP, DIP 등의 원칙을 지키려고 노력하였으며,
단일 로그인 세션을 구현해보고자 싱글톤 디자인 패턴을 적용하였다.
기간이 여유롭지 않아 부담 드는 부분이 있긴 했지만 만들면서 재밌었고, 다른 분들이 만들어낸 결과물이 정말 대단한 것들이 많아서 보면서 감탄했던 것 같다.
다른 분들과 교류하면서 더 배울 수 있는 기회를 늘려야겠다고 다짐하게 되기도 하였다.
[마무리하며]
대학 생활 중 제일 오점이라고 하면, 코로나가 터져 집에서 원격 수업을 들었던 2020-1학기였을 것이다.처음이자 마지막으로 2점대의 학점을 찍었었으며.. 나름대로 수업을 듣고 숙제도 했던 나로써는, 개발자라는 진로가 나에게 맞는 것인지 진지하게 고민하기도 하며 다소 우울했던 시기였다.자료구조, 확률 및 랜덤변수, 이산구조, 논리회로 등 지금 돌이켜봐도 조금 딱딱한 과목들을 많이 들었는데,수업을 제대로 집중해서 듣기 어려운 환경이어서 더더욱 수업내용을 잘 따라가지 못했던 것 같다.
여튼 그때 벽을 느꼈던 과목 중 하나가 자료구조였는데, 자료구조를 직접 구현하는 코드를 이번 수업을 통해 접하고보니흐름을 파악하는데 크게 어려움이 없어서 내가 한 층 성장했구나 느끼게 되는 부분이었다.(5년이라는 시간동안 성장을 안했으면 안되긴 하지만.. ㅋㅋ)
솔직히 아직도 안보고 생판 처음부터 자료구조를 구현하라고 하면 못할 것 같다.그래도 클래스 다이어그램과 해당 메소드의 역할을 설명하는 문서가 있다면, 그걸 보고서는 어떻게든 구현할 수 있지 않을까?정도의 레벨까지는 올라온 것 같다..
앞으로도 점점 발전해나가서 어엿한 1인분을 해낼 수 있는 개발자가 되기를 희망하며 마친다.
'Beyond SW > 주간 회고' 카테고리의 다른 글
| 한화시스템 Beyond SW캠프 15기 9주차 회고 (0) | 2025.03.24 |
|---|---|
| 한화시스템 Beyond SW캠프 15기 8주차 회고 (0) | 2025.03.17 |
| 한화시스템 Beyond SW캠프 15기 6주차 회고 (1) | 2025.03.03 |
| 한화시스템 Beyond SW캠프 15기 5주차 회고 (0) | 2025.03.02 |
| 한화시스템 Beyond SW캠프 15기 4주차 회고 (1) | 2025.02.17 |