_

Always be tactful

MAIN/My Study 22

07. 제네릭의 핵심 개념과 설계 철학

들어가며지난 28일, 자바 정규 수업을 들었다. 제네릭과 관련한 내용이었는데, 제네릭 사용 시 Type Argument를 정확히 일치시켜야 한다고 하더라. 2주라는 짧은 시간 안에 자바를 가르치다 보니 어쩔 수 없는 부분이었겠지만, 아쉽게도 '왜?'는 빠져있었다. 제네릭의 탄생제네릭이 도입되기 이전 시대에서, List와 Map 같은 자바 컬렉션은 모든 종류의 객체를 담을 수 있는 Object 타입으로 설계되었다. Object 클래스는 최상위 클래스로서, 언뜻 보면 유연하지만 그만큼 치명적인 단점을 안고 있었다. 예를 들어 아래와 같은 원시 타입 리스트가 있다고 하자.List items = new ArrayList();items.add("ssafy");items.add(14); 현재 리스트에는 문자열도, ..

MAIN/My Study 2025.07.30

06. 동적 배열의 재할당과 힙 오버플로우

동적 배열과 재할당자바에서 ArrayList는 대표적인 동적 배열이다. 내부적으로는 일반 배열을 사용하지만, 요소가 추가되거나 제거될 때 필요에 따라 배열의 크기를 자동으로 조절한다. 이러한 특징으로 개발자가 배열의 크기를 정할 필요 없이 유연하게 사용 가능하다는 장점이 있다.내부적으로는 용량 부족을 감지하고 현재 용량보다 더 큰 (일반적으로 1.5배) 배열을 생성해 모든 요소를 복사한다. 이후 새로운 배열을 참조하도록 변경하는 과정을 거친다. ArrayList의 경우, 배열의 인덱스는 int 타입으로 관리된다. int 타입의 최댓값은 2^31 - 1이니, 이론적으로는 약 21억 개의 요소를 가질 수 있다고 판단하기 마땅하다. 그러니 실제로 21억 개의 요소를 담아보자.import java.util.*;..

MAIN/My Study 2025.07.29

Common vs Global: 패키지 구조 이해하기

들어가기 전에가장 흔하게 사용되는 Common 패키지에 대해 말하자면, 결국 핵심은 구조화 및 가독성 향상이다.프로젝트를 진행하다 보면 프로젝트 내 여러 모듈이나 레이어에서 공통으로 쓰이는 코드가 생기기 마련이다. 코드 재사용성을 극대화하고 중복 코드를 방지하기 위해, 나아가 유지보수 측면에서 편리하기 위해 우리는 공통 코드들을 따로 빼게 된다. 이러한 코드들의 모음집이 Common 패키지인 셈이다.※ 사실 패키지 구조라는 게 명확한 답이 있는 건 아니다 보니 가벼운 마음으로 읽었으면 한다. Common vs GlobalCommon으로 퉁쳐서 사용하는 경우가 많은데 사실 Common 패키지와 Global 패키지는 서로 의미가 다르다.Common: 공통으로 사용되는 모든 코드를 모아두는 패키지Global:..

MAIN/My Study 2025.06.05

.prettierrc

import 정렬하기Code formatter로 Prettier를 쓰고 있었다.그동안 import는 신경 쓰지 않고 살았는데, 프로젝트 규모가 커지면서 상당히 지저분해짐을 느꼈다. 찾아보니 sort-imports 익스텐션을 추천하더라.그러나 막상 적용하고 보니 정렬 기준이 이상했고 커스텀하기도 어려웠다. 다른 방법도 여럿 시도했지만 썩 마음에 들지 않았다. prettier-plugin 사용하기결국 선택한 방법은 Prettier 플러그인을 사용하는 것이다.(그동안 Prettier 플러그인으로 sort-imports가 있는 줄 몰랐다.)# 플러그인 설치npm install --save-dev prettier @ianvs/prettier-plugin-sort-imports플러그인 설치 후, 루트 디렉토리에 아..

MAIN/My Study 2025.06.04

Database driver: undefined/unknown

문제 상황Spring Boot 3.4.3에서 JPA를 추가하니 아래와 같은 로그가 출력되었다. Database JDBC URL [Connecting through datasource 'HikariDataSource (HikariPool-1)'] Database driver: undefined/unknown Database version: 9.3 Autocommit mode: undefined/unknown Isolation level: undefined/unknown Minimum pool size: undefined/unknown Maximum pool size: undefined/unknown 해결 방법연결부터 제대로 해야 한다는 생각에 고칠 생각부터 했다. "왜..

MAIN/My Study 2025.05.24

Docker Compose에서 MySQL 데이터 영속성 설정하기

🐳 도커 컴포즈최신 버전에서는 Docker Desktop이 기본적으로 Docker Compose v2를 포함하고 있어서 별도로 설치할 필요 없이 사용할 수 있다.과거에는 도커 컴포즈가 별도 바이너리로 취급되어 직접 설치하는 과정이 요구되었으며, dokcer-compose 명령어를 사용했다.# 설치 확인docker compose version# 출력 예시Docker Compose version v2.34.0-desktop.1docker-compose.yml # 기본 공통 구성docker-compose.override.yml # 로컬 전용 설정 (자동 인식)docker-compose.prod.yml # 운영 환경 전용.env # 환경변수데이터..

MAIN/My Study 2025.05.23

도커 설치하기 (MySQL 포함)

도커 설치개발환경과 완전히 같은 환경을 구축하기 위해 도커를 설치하자. Docker: Accelerated Container Application DevelopmentDocker is a platform designed to help developers build, share, and run container applications. We handle the tedious setup, so you can focus on the code.www.docker.comMac / Windows 정도는 당연히 구분하겠지만, 간혹 AMD64와 ARM64를 구분하지 못하는 경우가 있다.실행 단축키 (Win + R) → `cmd` 입력 → 명령어 `wmic os get osarchitecture` 입력`64-bit`이 ..

MAIN/My Study 2025.05.15

유휴 상태 콜백 메서드와 병렬 처리로 최적화 할 수 있을까?

스크롤 이벤트일부 로직이 로컬 스토리지를 사용하는 경우, 메인 스레드를 차단할 우려가 있어 requestIdleCallback을 통해 브라우저가 유휴 상태일 때만 실행되도록 고려하였으나, 현재 실질적으로 사용하고 있는 로직은 간단한 연산 후 DOM에 스타일만 반영하는 수준이므로 쓰로틀 + 디바운싱 구조만으로도 충분하다고 판단하였다. 오히려 requestIdleCallback을 사용하면 불필요한 지연이 발생할 수 있다. 메인 스레드를 막을 정도로 무거운 작업이 추가된다면 그때 다시 고려해야겠다. 현재로서는 성능보다 UX 측면에서 지연으로 인한 부작용이 생길 가능성이 다분하다. *Progress Bar가 실질적으로 사용자 경험 향상에 도움이 되지 않는다면, 완전 삭제도 고려하고 있다. 스크롤 이벤트 자체가 ..

MAIN/My Study 2025.05.05

세이브 취소/타이틀 축약/잔여 용량 체크/기억 잔존율 시각화

일단 기능 구현부터 마치기로 했다.최적화 문제는 어차피 아무리 고민해도 끝이 없다. 막상 배포하고 나면 예상하지 못한 곳에서 새로운 이슈가 분명 터질 것이다.구현 목록1. 매뉴얼 세이브 취소 *아주 작은 이슈가 있었는데 해결했다.이제는 사용자가 직접 등록한 웹 페이지에 대해 직접 삭제할 수 있다.*HTML이 익숙하지 않아 컨테이너 실수한 거랑 삭제 후 갱신된 정보로 새로 호출하지 않아 미적용되던 문제였다.2. 타이틀 축약 및 툴팁 제공 타이틀이 너무 긴 웹 페이지인 경우, 타이틀을 축약해 표시하도록 패치했다.사용자가 마우스를 갖다 대면, 툴팁 형식으로 풀 타이틀이 제공된다.3. 잔여 용량 정보 확인 사용자가 현재 사용 중인 용량을 직접 알 수 있게 되었다.이를 통해 조금 더 원활한 관리가 가능할 것으로 ..

MAIN/My Study 2025.04.24

배열 순회 문제와 팝업 진행률 이슈

현재는 savedSites 배열을 순회하며 새로 넘겨받은 url과 일치하는 사이트가 있는지, 인덱스를 통해 중복을 판단한다. 만약 중복이라면 url을 제외한 모든 요소를 갱신하고 있다. (title, lastAccessed, scroll, height) 팝업의 경우, Manual Save를 누를 때마다 진행률이 갱신된다.실제 진행률을 동적으로 반영하지 않아, 사용자가 직접 갱신해 주는 것이나 다름없다. 아쉬운 점이 몇 가지 보인다.일단 첫째, Map으로 관리했다면 어땠을까?왜 배열로 관리했을까?Map을 사용할 경우, 직렬화 이슈가 발생한다.배열은 JSON으로 자동 변환되지만, Map은 그렇지 않기 때문이다. 그럼에도 불구하고, 로직상 Map이 훨씬 깔끔하고 빠른 건 명백하다.적절한 변환 과정만 거치면 충..

MAIN/My Study 2025.04.23

크롬 확장 프로그램을 개발하자 (Where Was I?)

Where Was I?Where-Was-I?는 크롬을 통해 여러 웹 페이지를 오가는 사용자들을 위해 만들어졌다. 바쁜 현대 사회 속에서, 우리는 참 다양한 웹 페이지를 이용하게 되는데,여기서 문제는, 자주, 혹은 가끔이라도 재방문해야 하는 경우가 존재한다는 것이다.북마크는 WWI를 대체할 수 없다.크롬에서는 자주 이용하는 웹 페이지를 북마크로 관리할 수 있다.그렇다면 Where-Was-I?는 왜 필요한 걸까? 답은 간단하다.북마크는 Where-Was-I?를 대체할 수 없다.1. 북마크의 관리 범위는 상당히 제한적이다.웹 페이지를 북마크에 직접 등록해야 하는 수고스러움이 있다.나는 이것에 대해 사용자 의존도 문제라고 부른다.사용자가 북마크 하는 것을 깜빡할 수 있다.사용자는 북마크 대상을 명확히 구분할 능..

MAIN/My Study 2025.04.22

Vite 기반 번들링 환경 구축과 타입 안정성을 위한 TS 마이그레이션

번들링 환경 구축Vite를 사용할 예정인데, 그러려면 일단 Node.js부터 설치해야 한다.*Node.js가 설치되어 있는지는 터미널에서 node -v로 간단하게 확인 가능하다.공식 사이트에서 LTS 버전 다운로드하고 설치하면 된다.참고로, 설치 과정에서 npm도 같이 깔리니 따로 설치할 필요는 없다.설치가 끝나면 node -v, npm -v 찍어서 확인하자.아마 높은 확률로 이렇게 뜰 텐데, PowerShell 보안 정책상 npm 실행이 차단된 상태라고 볼 수 있다.Windows PowerShell은 .ps1 스크립트 실행을 막아서 실수나 악성 코드 실행을 방지하려고 한다. npm.ps1도 일종의 스크립트이기 때문에, 기본 정책인 Restricted에서는 사용할 수 없다. 관리자 권한으로 실행해 다음 ..

MAIN/My Study 2025.04.19

개인 프로젝트지만 협업처럼 행동하자 (git flow, inject issue?)

들어가며항상 들려오는 말이 있다."아무리 능력이 뛰어난 사람이라도 같이 일하기 어려운 상대는 기피하게 된다." 개발에서 말하는 협업은 단순히 사람 대 사람으로서 말이 잘 통하느냐를 의미하지 않는다.개인 프로젝트지만, 마치 협업인 것처럼 행동하자.깃 브랜치란 무엇이며, 왜 있는 걸까?커밋은 어떻게 하는 게 좋을까?브랜치 관례와 커밋 관례를 찾아보며, 이번 프로젝트에서 최대한 적용해보려 한다.리포지토리아래 깃허브 링크를 남겨두겠다.기획부터 개발, 배포, 마케팅까지 고독하지만 재미있는 기록이 될 것이다. GitHub - funczun/where-was-iContribute to funczun/where-was-i development by creating an account on GitHub.github.co..

MAIN/My Study 2025.04.18

불편함이 개발로 이끌었다

개발 동기경영학부 학생인 나는 개발자를 꿈꾸며 멋쟁이사자처럼이라는 동아리에 가입하게 되었다. 감사하게도, 우리 동아리 운영진은 유용한 아티클을 종종 공유해 주곤 한다. 문제는 나에게 있다. 공유받은 아티클을 그때그때 읽으려 노력하지만, 개수가 많고 분량도 적지 않아 한번에 소화하기 어려웠다. 웹사이트 자체가 유용하다 싶으면 북마크 해두고, 그게 아니라면 해당 링크만 카톡방에 저장해 두었다가 다시 보는 편인데, 이 부분에서 적지 않은 피로감을 느꼈다. 크게 불편하지는 않지만 개선시키면 좋을 것 같다는 생각이다.문제 상황1. 마지막으로 읽었던 지점을 찾아야 한다.아티클을 읽다가 중단하고 나중에 다시 읽으려 할 때, 마지막 위치를 기억해 찾아야 하는 번거로움이 있다.2. 읽고 있던 아티클을 깜빡 잊는 문제가 ..

MAIN/My Study 2025.04.17

컴퓨터의 연산 방식 (feat. 1의 보수 & 2의 보수)

들어가기에 앞서,컴파일이란 무엇인가? C, C++, Java, Python 같이 우리가 일반적으로 사용하는 프로그래밍 언어를 고급 언어라고 하며, 기계어와 어셈블리어를 저급 언어라고 한다. 가장 쉬운 구분법은 해당 언어가 인간친화적인지 기계친화적인지를 따지는 것이다. 인간친화적인 고급 언어는 우리가 읽고 쓰기 편하지만 이를 그대로 전달한다면 컴퓨터는 이해할 수 없다. 이유를 간단히 설명하자면, 컴퓨터는 전기 신호를 바탕으로 이해하는데 이를 `있다(1)`와 `없다(0)` 정도로만 구분하기 때문이다. CPU가 직접 해석하고 실행할 수 있도록, 사람이 작성한 고급 언어인 `코드`를 `기계어`로 번역하는 것을 `컴파일`이라고 한다.소스 코드를 실행 가능한 파일로 만드는 전체 과정을 `빌드`라고 하며, 컴파..

MAIN/My Study 2025.03.26

최적화 문제를 위한 DP (탑다운, 바텀업 방식)

다이나믹 프로그래밍은 시간 단축을 위한 알고리즘이다. 탑다운 방식과 바텀업 방식이 존재하며, 결국 핵심은 계산한 값을 저장하고 재활용한다는 것이다.동적 계획법(DP)를 구현해 보자. 탑다운: 메모이제이션 이름에서 알 수 있듯 큰 문제부터 작은 문제로 해결하는 방식이다. ✅ 재귀구조가 직관적이고 구현이 간단하다. ✅ 재귀호출이 깊어질수록 스택 오버플로우 가능성이 있다.public class Fibonacci { static int[] dp; public static int fibonacci(int n) { if (n 바텀업: 터뷸레이션 이름에서 알 수 있듯 작은 문제부터 큰 문제로 해결하는 방식이다. ✅ 스택 오버플로우 위험이 없으며 모든 값에 쉽게 접근할 수 있다.✅ 반복문을 ..

MAIN/My Study 2025.02.28

그래프 탐색 알고리즘 BFS 풀이

인사말 모두들 안녕하신가요. 저는 어느덧 알고리즘을 건든 지 140일 지났답니다. 기쁜 소식이 있어 전해드리자면, 최근에 BFS 문제들을 풀며 골드 구간에 진입했어요. 목표는 골랜디 마스터고요. 이번에 문제를 풀며 스스로 아쉬웠던 부분들이 있어서 지금의 생각과 감정을 기록하려고 글을 적습니다.BFS인데 그래프가 2개?package bfs;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.LinkedList;import java.util.Queue;public class Problem10026 { static final int[] dx = {0, 0, -1,..

MAIN/My Study 2025.02.27

컴퓨터에서 실수는 어떻게 저장될까?

컴퓨터에서 실수는 어떻게 저장될까? 컴퓨터는 모든 정보를 2진수로 표현한다. 실수 역시 2진수로 표현해 RAM에 저장하게 되는데, 이 과정에서 실수 값 일부가 손실되어 정확한 값이 아닌 근삿값을 저장하게 된다. 예를 들어, 0.1을 2진수로 표현하면 0.00011001100110011...이라는 무한소수가 된다. 숫자 하나를 저장하는 bit는 통상적으로 32비트이므로 뒷부분이 잘려나가게 되고, 이로 인해 오차가 발생하여 실제로 저장되는 값은 0.10000000000000000555...가 되어 미세한 오차를 발생시킨다. ▶ 자료형 double을 활용하자. C언어라면 double 자료형을 활용해서 숫자 하나당 64비트를 배정하여 오차를 급격하게 줄일 수 있지만 메모리 용량이 2배가 필요하다는 단점이 있다..

MAIN/My Study 2024.12.14

파이썬에서 리스트를 뒤집는 세 가지 방법

리스트를 뒤집는 3가지 방법 [::-1] 리스트를 역순으로 슬라이싱 하는 방법이다. 새로운 리스트를 만들 필요 없이 기존의 리스트를 뒤집어 반환한다. 하지만 슬라이싱을 활용해 뒤집는 경우 리스트의 크기가 매우 크다면 메모리를 필요 이상으로 낭비하게 될 수 있다. reverse() 원본 리스트를 직접 뒤집기 때문에 메모리 사용량이 적다. 하지만 원본 리스트가 변경되기 때문에 원본 리스트를 유지하고 싶다면 사용하지 않아야 한다. reversed() 반환하는 값이 iterator이기 때문에 원본 리스트가 바뀌지 않으면서 메모리 사용량이 적다. 하지만 바로 사용할 수는 없어 list()를 통해 리스트 형태로 변환 후 사용하게 된다.결론 원본 리스트를 변경해도 상관 없는 경우 → reverse() 원본 리스트를 ..

MAIN/My Study 2024.12.07

문자열 결합 연산을 쓰면 안 되는 이유

시간 복잡도 프로그래밍 언어에서 시간복잡도란 입력의 크기(N)에 따라 알고리즘이 얼마나 많은 "시간"을 소모하는지를 나타내는 척도이다. 표기법은 다양하나, 일반적으로는 O(1), O(n), O(log n), O(n^2) 등의 표기법을 사용한다.실제 코드 시간 복잡도 분석import sysN = int(sys.stdin.readline())result = ""for i in range(N // 4): result += "long "result += "int"print(result) 백준 25314번 문항을 풀며 실제 내가 제출한 코드로, 입력값 N에 따라 "long "을 N // 4번 반복해서 결과 문자열에 추가한 후, 마지막에 "int"를 붙여서 출력하는 프로그램이다. 다음은 코드를 쪼개어 각 코드..

MAIN/My Study 2024.11.19
728x90