캡슐화란 무엇인가?캡슐화는 객체지향 프로그래밍(OOP)에서 구체적인 것을 숨기고, 추상적인 것만을 드러내는 개념입니다. 이를 통해 클라이언트 객체(Client)가 세부적인 구현에 의존하지 않게 하여, 변경에 유연한 코드를 작성할 수 있도록 도와줍니다. +) 구체적인 것&추상적인 것은 낮은 수준&높은 수준이라고 부르기도 함. DIP!! 클라이언트 객체란?클라이언트 객체는 협력 과정에서 요청을 보내는 객체를 의미합니다. 캡슐화를 통해 클라이언트 객체가 구체적인 구현에 의존하지 않게 하여, 변경의 전파를 막는 것이 핵심입니다. 캡슐화의 목적캡슐화의 목적은 구체적인 것을 Client 객체로부터 숨겨 변경이 Client 객체에 전파되지 않도록 하여 시스템을 유연하게 만드는 데 있습니다. 이를 통해 낮은 결합도를 ..
JPA 코드에서 JDBC 코드로 변경하기이 글에서는 JPA로 작성된 코드를 JDBC로 변경하는 과정을 살펴보겠습니다. JPA는 객체와 데이터베이스 간의 매핑을 자동으로 처리해 주지만, JDBC는 우리가 직접 SQL을 작성해야 하고 데이터베이스와의 연결을 수동으로 처리해야 합니다. 아래에서 JPA 코드를 JDBC로 변경하는 방법을 단계별로 진행해 보겠습니다. JPA로 작성된 Product 클래스먼저, JPA를 사용해 작성된 Product 클래스입니다. JPA는 어노테이션을 통해 데이터베이스 테이블과의 매핑을 쉽게 처리할 수 있습니다.@Entity@Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Product extends BaseE..
숫자 야구 게임 과제가 끝나고 제 프로젝트를 돌아보며 잘한 점과 못한 점에 대한 회고를 하려고 합니다.잘한 점통일된 예외 처리BaseballException을 상속받는 다양한 예외 처리를 통해 통일감 있고 규칙적인 예외 처리를 구현했습니다. 무질서하게 흩어져 있을 수 있는 예외 상황을 하나의 규칙 아래 묶음으로써, 예외 처리 코드의 가독성과 유지보수성을 크게 높일 수 있었습니다.개인 과제였지만, 이러한 일관성 있는 처리 방식은 협업 시에 큰 장점으로 작용할 것입니다. 향후에는 다양한 예외 상황을 다루면서 예외 메시지와 상태 코드를 정의하여 더 정교한 예외 처리를 시도해 볼 계획입니다. 메서드 파라미터에 final메서드 파라미터에 final 키워드를 사용하면서, 불변성을 보장할 뿐만 아니라 휴먼 에러를 예..
로깅을 왜 해야 할까?운영 서버에서 항상 문제가 발생하지 않기를 바라지만, 이는 매우 어려운 일입니다. 시스템이 복잡해질수록 문제는 더 자주 발생할 수 있고, 이를 해결하기 위해서는 로그가 필수적입니다. 로그는 단순한 기록이 아니라, 시스템의 행동을 이해하고 문제를 추적하는 데 있어 개발자와 운영팀의 비밀 무기입니다. 예를 들어, 한 사용자가 웹 애플리케이션에서 특정 기능을 사용하다가 오류를 경험했다고 가정해 봅시다. 문제를 해결하기 위해 개발자는 로그를 확인하려고 합니다. 하지만 로그가 명확한 정보 없이 단순히 "오류 발생"이라고만 적혀 있다면, 어떤 상황에서 문제가 발생했는지, 어떤 사용자가 영향을 받았는지를 파악하기가 매우 어렵습니다. 이런 상황에서 개발자는 로그를 해석하는 데 많은 시간을 소모하고..
Java의 탄생 배경자바가 등장할 당시, C/C++과 같은 언어들이 주로 사용되었지만, 이 언어들은 특정 플랫폼(OS)이나 하드웨어에 맞춰 컴파일되도록 설계된 언어였다. 각 플랫폼마다 사용하는 CPU에 따라 해당 환경에 맞게 컴파일해야 했다. 이런 한계를 극복하기 위해 Sun Microsystems는 OS나 하드웨어에 상관없이 다양한 환경에서 실행될 수 있는 언어를 만들기로 결심했고, 이것이 자바의 탄생으로 이어졌다. 자바는 “Write Once, Run Anywhere”라는 철학을 기반으로 다양한 플랫폼에서 동일한 코드를 실행할 수 있도록 설계된 언어이다. JAVA의 동작 원리JVM을 설명하기 전에, 자바 프로그램이 어떻게 동작하는지 기본적인 원리를 먼저 살펴보겠다.자바로 작성된 소스 파일은 보통 이름..
새로운 클래스에 대한 고민과 결정Lv4에 들어서면서 자릿수에 대한 요구 사항이 있었다. 이에 따라 GameManager에서 필드로 digitSize를 가지고 있게 생각을 하였는데, 좀 더 객체 지향적으로 개선하기 위해 책임의 분리와 확장성을 고려하며 이에 따라 개선한 과정을 작성하려고 한다. 고민의 코드public class GameManager { private final BaseballGame baseballGame; private final GameStats gameStats; private final int digitSize; public GameManager() { this.gameStats = new GameStats(); this.base..
GameManager 설계 고민과 해결계산기 과제 Level 2, Level3에서는 GameManager 클래스가 게임의 전반적인 흐름을 제어하고 사용자 입력에 따라 게임을 시작하거나 기록을 조회하는 역할을 한다. 이 과정에서 몇 가지 설계 고민이 있었고, 그에 대한 해결책을 마련하였다. 이번 포스트에서는 이 고민과 해결책에 대해 자세히 살펴보겠다. 고민 1: GameManager 생성 시 BaseballGame 인스턴스 초기화public class BaseballGame { private final NumberGenerator numberGenerator; private final Referee referee; public BaseballGame(final NumberGenera..
지난 계산기 과제에서 Exception을 상속하여 예외 처리를 하던 중 코드가 지저분해지는 문제가 발생했다. 매번 try-catch 문을 사용해야 했고, 그로 인해 코드가 길어지며 가독성도 떨어졌다. 그래서 RuntimeException으로 변경하여 try-catch 문을 생략하게 되었다. 왜 RuntimeException으로 변경하면 try-catch 문을 생략할 수 있었을까?Exception을 상속받으면 해당 예외는 CheckedException이 된다. CheckedException은 컴파일러가 예외 처리를 강제하기 때문에, 메서드 내에서 반드시 try-catch로 처리하거나 메서드 선언부에 throws를 붙여야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 하지만 RuntimeExcepti..
스프링 부트를 사용한 애플리케이션 개발에서 테스트는 매우 중요한 역할을 한다. 적절한 테스트는 코드의 안정성과 품질을 보장하고, 예기치 못한 오류를 사전에 방지할 수 있게 해 준다. 스프링에서는 다양한 테스트 방법을 제공하는데, 그중에서도 Mock을 활용한 단위 테스트와 SpringBootTest를 사용한 통합 테스트는 자주 사용되는 두 가지 방식이다. 이번에는 이 두 가지 테스트 방법의 차이점과 각각의 사용 목적에 대해 설명해보려고 한다. @Mock먼저 Mock을 사용한 테스트이다.@ExtendWith(MockitoExtension.class)class ProductServiceTest { @Mock private ProductRepository productRepository; ..
ArrayList는 Java에서 List 인터페이스를 구현한 인기 있는 데이터 구조이다. 이번 글에서는 동적으로 크기가 조절되는 배열을 제공하는 ArrayList의 내부 저장 방식과 성능에 대해 살펴보려고 한다. ArrayList의 초기화 과정ArrayList를 생성할 때, 기본적으로 빈 배열을 사용하여 초기화된다. 기본 용량은 일반적으로 10이며 처음에는 빈 배열이 할당된다. +) 리스트의 size가 10이 아님! add 메서드 작동 방식add(E e) - 끝에 요소 추가위 사진은 ArrayList의 리스트 끝에 요소를 추가하는 add 메서드 내부 코드이다. 코드를 하나하나 살펴보자.modCount++ : 리스트가 수정될 때마다 증가하는 값이다. 이 값은 여러 스레드에서 ArrayList..