일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 운영체제
- BFS
- stack
- 디바이스 입출력
- 파이썬
- 코딩 테스트
- 백준 #
- DP
- 백준
- 스택
- integretion test
- java
- SW Expert Academy
- 유니크 키
- error
- Python
- 데드락
- 논리 메모리
- 다익스트라
- queue
- OOP
- DFS
- 객체지향 프로그래밍
- 큐
- 프로세스
- 캡슐화
- unionfind
- OSTEP
- jacoco
- OS
- Today
- Total
목록전체 글 (33)
middlefitting
정의 RDBMS 키는 데이터를 식별하고 정렬하는데 사용되는 하나 또는 여러개의 필드를 의미한다. 이는 데이터의 제약조건과 관계를 정의하고 무결성을 유지하는 중요한 역할을 담당한다. 키를 구성하는데 있어 고려할 점은 그것이 현재 상태에 한정되지 않고 영원하다는 것이다. 따라서 비즈니스상 키의 속성이 항상 유지될 수 있을지 충분히 고려하고 키를 선정하여야 한다. 종류 해당 글에서는 이론적인 개념만 가지는 키를 이론적 키로, 물리적으로 구현될 수 있는 키를 물리적 키로 구분한다. 이론적 개념은 테이블에서 식별된 것을 의미한다. 물리적 개념은 식별된 것을 데이터베이스 시스템에 구현한 것을 의미한다. 이론적 키 1) 슈퍼키 슈퍼키는 유일성의 특성을 만족하는 속성들의 집합을 말한다. 유일성이라는 것은 하나의 릴레이..
로컬 테스트 코드를 작성하다 보면 꽤 곤란한 문제를 마주치게 된다. 보통 DB를 사용하는 서비스들이 많은데 DB에 대한 독립성 제공이 어려운 것이 그 이유이다. 테스트 용으로 로컬에 DB를 따로 만들어도 트랜잭션을 실수로 걸지 않는 등의 문제로 DB에 데이터가 들어가버리는 문제 등, 번거로운게 많다. 또한 로컬 환경에 의존하는 테스트는 CI 구축이 어려워진다. 예를 들어 mysql을 사용하려면 mysql이 설치되어 있어야 하지 않는가. CI로 많이 사용하는 깃허브 액션에서 mysql을 설치하고 테스트를 돌리는 것은 굉장히 비효율적으로 보인다. 그렇다고 인메모리 데이터베이스 h2를 통해 대체하는 것은 완전하지 않다. 독립적이고, 환경에 종속적이지 않은 그런 테스트는 어떻게 할 수 있을까. 자연스럽게 도커가..
테스트 코드를 작성하다 보면 테스트 커버리지를 측정하고 싶은 경우가 생긴다. 측정을 넘어 테스트 커버리지에 제약을 걸어 새로 프로젝트의 커버리지를 높게 유지하고 싶다는 생각도 자연스럽게 생긴다. jacoco는 커버리지, 측정, 검증 도구로써 이런 고민을 해결해 줄 수 있다. 해당 글에서는 jacoco를 활용하여 단위 테스트와, 통합 테스트의 커버리지 측정 및 검증을 하는 방법을 알아보도록 한다. 환경은 스프링 부트, gradle 을 기준으로 한다. 우선 단위 테스트와 통합 테스트를 분리해서 측정하기 위해서는 해당 태스크가 분리되어 있어야 한다. 분리를 할 수 있는 방법은 아래의 글을 참고할 수 있다. https://middlefitting.tistory.com/103 스프링에서 단위 테스트, 통합 테스트..
스프링에서 테스트 코드를 작성하다 보면, 통합 테스트와 단위 테스트를 주로 작성하게 된다. 그런데 테스트 코드가 점점 많아지면서 관리에 어려움이 생긴다. 커버리지 측정에 있어 단위 테스트와 통합 테스트를 분리하고 싶은 경우도 생기고, 각각의 테스트를 분리해서 실행시키고 싶은 경우가 존재하는데 gradle에서 기본적으로 제공하는 Test 태스크는 모든 테스트를 한번에 실행시키기 때문에 파일의 구분이 어렵다. 근데 스프링과 JUnit에서는 당연히 해당 내용에 대한 해결책을 제시한다. 나와 비슷한 고민을 한 분들을 위해 gralde, JUnit, Spring에서 간단한 방법으로 단위 테스트와 통합 테스트를 구분하는 방법을 공유하고자 한다. 1) Tag 활용하기 @Tag 해결 방법은 아주 간단하다. JUnit..
테스트 코드가 중요하단 것은 개발을 공부하는 모두가 알고 있다. 그런데 생각보다 실천에 옮기기 어렵다. 실제로 학생으로써 개발을 공부하며 다양한 사이드 프로젝트에 참여해 왔지만, 테스팅 환경이 잘 구성된 경우는 없었다. 테스트 코드가 존재하더라도 이미 다 깨진 테스트 코드가 대부분이었고, 관리는 전혀 이루어지지 않았다. 테스트 코드는 잘 작성하지 않는 이유는 무엇일까. 이유는 다양하겠지만, 테스트 코드를 작성하는 시간이 아깝다고 느끼는 경우가 많은 것 같다. 기능 구현하기도 바빠서 테스트를 짤 시간이 없다는 생각이 대부분의 이유이다. 근데 기능 구현이 끝나도 테스트 코드를 잘 작성하지 않는다. 심지어 배포 이후에 버그가 펑펑 터지고 그걸로 고생하는 경우가 생겨도 테스트 코드를 작성하지 않는다. 이런 상황..
프로그램과 프로세스 프로그램과 프로세스, 같은 말처럼 들릴 수 있지만 둘은 엄연히 차이가 있습니다. 둘의 차이는 그 둘의 정의를 통해 알 수 있습니다. 프로그램 디스크 상에 존재하는 실행을 위한 명령어와 정적 데이터의 묶음 프로세스 실행중인 프로그램 운영체제의 관점에서 프로그램은 생명이 없는 정적 데이터일 뿐입니다. 운영체제가 프로그램을 실행시키면서 생명을 불어넣게 되고 프로세스가 되는 것입니다. 프로그램의 실행 1. 메모리 탑재 그렇다면 어떻게 프로그램은 실행될 수 있는 걸까요. 쉽게 생각하면 하드웨어 공간을 통해 이를 알 수 있습니다. 프로그램이 존재하는 공간은 SSD, HDD와 같이 흔히 '하드' 라 불리는 영구기억장치에 존재합니다. 운영체제의 작업 공간은 Ram 이라 불리는 휘발성 메모리 영역에 ..
이 글은 객체지향 프로그래밍 캡슐화 개념을 모르시거나 모호하다고 느끼는 분들을 위한 글입니다. 다음과 같은 내용으로 시작합니다. 우리는 OOP 4대 원칙인 캡슐화를 준수하기 위해, 흔히 멤버 변수를 접근 제어자를 통해 숨기고 getter, setter 메서드를 통해 우회해서 접근 및 수정하도록 합니다. 근데 이 부분에서 우리는 다음과 같은 의문을 가지게 됩니다. 접근 제어자 걸어도 getter, setter 선언하면 public으로 선언하는 것과 캡슐화 측면에서 무슨 차이가 있는걸까? 그말이 그말인것 같은데 무슨 차이가 있으며, getter setter가 왜 캡슐화를 위해 사용된다는 것인지 의문을 품게 되는 것입니다. 결론을 이야기 하자면 차이가 없습니다. 즉 캡슐화를 위배한다는 것은 다를바가 없는 것이..
메서드 오버로딩이란 메서드 오버라이딩이란 상위 클래스에서 이미 정의된 메서드를 하위 클래스에서 다시 정의하는 것을 말합니다. 하위 클래스는 상위 클래스보다 많은 멤버를 가지게 되고, 이러한 특성은 자연스럽게 메서드 오버라이딩이 필요한 여러 상황을 만들게 됩니다. 메서드 오버라이딩을 통해 하위 클래스는 상위 클래스의 메서드를 재사용하면서 자신만의 새로운 기능을 추가할 수 있습니다. 메서드 오버라이딩의 목적 메서드 오버라이딩의 목적을 좀 더 자세히 살펴보면 다형성 구현, 유지보수성 향상, 확장성 확보가 존재합니다. 하나씩 살펴보면 다음과 같습니다. 다형성 구현 하위클래스는 상위 클래스의 메서드를 재정의함으로써 하위 클래스 동작 방식을 다양화할 수 있습니다. 유지보수성 향상 부모클래스의 메서드가 변경되는 것은..
추상화란 추상화는 객체지향 프로그래밍의 4대원칙 중 하나로, 객체의 공통적인 특성을 추출하여 인터페이스나 추상 클래스로 정의하는 것을 말합니다. 이들은 공통적으로 추상 메서드를 가지고 있으며 추상 메서드는 구현된 것이 전혀 없는 설계도라고 할 수 있습니다. 추상화를 통해 객체의 복잡한 내부 구현을 숨기고 객체 간의 관계를 단순화할 수 있습니다. 더불어 추상화는 상속, 다형성, 캡슐화와 함께 사용됨으로써 객체지향 프로그래밍의 핵심인 객체의 코드 유지보수성과 가독성을 제공할 수 있습니다. 추상화를 왜 사용하여야 할까? 추상화를 사용하면 다음과 같은 장점을 얻을 수 있습니다. 1. 필요한 정보에만 집중 객체의 내부 구현은 객체를 구성하는 속성과 메서드 등으로 이루어져 있습니다. 그리고 이 내부 구현은 종종 매..
다형성이란 객체지향의 4대원칙중 하나로 다형성을 잘 이해해야 객체지향을 잘 이해할 수 있다고 합니다. 다형성이란 단어 그대로 여러가지 형태를 가질 수 있는 능력을 말합니다. 다른 말로는 조상 타입의 참조 변수로 자손 타입의 객체를 다룰 수 있는 것을 말합니다. "부모는 자식을 품을 수 있다" 라는 문장을 통해 좀 더 편하게 외우실 수 있습니다. 다형성 예시 import java.util.Objects; public class Parent { String house; } class Child extends Parent{ public Child(String house) { this.house = house; } void print_variable() { System.out.println(house); } }..
상속이란 객체지향 프로그래밍에서 상속이란 기존의 클래스로 새로운 클래스를 작성하는 것을 말합니다. 즉 상속을 통해 두 클래스를 부모와 자식의 관계를 맺어줄 수 있습니다. 상속 규칙 상속에 있어서 다음과 같은 규칙들이 존재합니다. 1. 자손은 생성자와 초기화 블록을 제외한 조상의 모든 멤버를 상속받는다. 다음과 같은 코드를 통해 이해할 수 있습니다. public class Parent { String house = "Seoul"; } class Child extends Parent{ int age = 20; void print_variable() { System.out.println(house); System.out.println(age); } } class main_logic { public static..
캡슐화는 OOP의 4대원칙 중 하나로 원칙인 만큼 매우 중요합니다. 클래스는 서로 관련이 있는 변수와 함수를 하나의 객체로 모아주는 역할을 수행하는데요, 캡슐화는 이러한 클래스의 멤버를 외부에서 쉽게 접근하지 못하게 정보를 은닉하는 것을 말합니다. 정보를 은닉하면 뭐가 좋을까 우선 캡슐화를 하지 않고 객체의 인스턴스 변수를 외부에서 접근하는 것은 객체지향스럽지 않습니다. 4대 원칙에 어긋나니까 당연한 말이지만 어떤 부분에서 그럴지 생각을 해보자면 왜냐하면 객체는 클래스에 있는 메소드로서 자신의 작업을 수행하게 되는데, 클래스에 정의되지 않은 동작으로 객체를 사용하게 되는 것이기 때문입니다. 더불어 그러한 의도되지 않은 동작은 오류의 범위를 크게 만들 것임은 분명합니다. 그래서 클래스의 정보를 은닉함으로써..
백준 1992 쿼드 트리 문제입니다. 파악해야 하는 사각형 범위가 모두 0으로 되어 있거나 1로 되어있다면 해당 숫자를 출력하고 그렇지 않다면 재귀를 타고 가면서 동일한 과정을 반복하는 문제입니다. N이 64밖에 되지 않으므로 O(N**2) 으로도 문제를 해결할 수 있습니다. 저는 분할 정복 방식으로 문제를 해결하였습니다. 제가 작성한 코드는 다음과 같습니다. N = int(input()) arr = [] for i in range(N): arr.append([]) temp = list(str(input())) for j in range(N): arr[i].append(int(temp[j])) def div_logic(tx, ty, length): next_length = length // 2 print..
this와 this()에 이어 super와 super()에 대해 알아보도록 하겠습니다. 이 둘도 완전히 다른 내용인데요, 결론부터 말하면 super는 조상의 멤버를 가리키며, 조상의 멤버를 자신의 멤버와 구분하기 위해 사용하고, super()는 조상의 생성자를 호출하는데 사용합니다. 참조변수 super public class Chair { String color; int weight = 20; } class ChairChild extends Chair{ int weight = 10; void info() { System.out.println(super.weight); System.out.println(weight); } public static void main(String[] args) { ChairC..
this() 와 this 의 차이 개인적으로 생성자 this()와 참조 변수 this는 상당히 낯선 친구들이었습니다. 둘의 차이는 완전히 다른 존재라는 것입니다. 비슷하게 생기긴 했지만 말이죠. 어떤 역할을 하는지 하나씩 알아보도록 하겠습니다. 생성자 this() this()는 생성자에서 호출하는 다른 생성자를 말합니다. 생성자에서 다른 생성자를 호출하는 경우는 무엇이 있을까요. 다양한 이유가 있겠지만 결국 코드의 중복을 줄이기 위해 사용할 것입니다. 생성자는 오버로딩이 가능한데 생성자마다 인스턴스 변수를 초기화하는 과정이 겹칠 수 있으니 그러한 부분을 줄일 수 있다는 것입니다. 예를 들어 다음과 같은 경우 활용할 수 있을 것입니다. public class Chair { String color; int ..