All in One SEO v4.9.10에서 생성된 이 파일은 llms.txt 파일로, LLM이 사이트를 색인화하는 데 사용됩니다. # stack stack from platanus ## Sitemaps - [XML Sitemap](https://platanus.kr/sitemap.xml): Contains all public & indexable URLs for this website. ## 글 - [#2 모두 서비스를 만드는 시대에서 놓치는 것 (책소개)](https://platanus.kr/post/4018) - 사용자 입장에서 생각하세요 - 책소개 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 저자 : 정그린 출간 : 한빛미디어, 2026 이 글은 릴리즈스톡 개발 시리즈 와 이어집니다. 우리는 오늘날 AI의 힘을 빌려 누구나 생각만 하던 아이디어를 서비스로 구현해보는 시대가 되었다. 그렇게 와이어프레임과 MVP까지 만드는데는 30분이 걸리지 않고, 밑단 작업까지 하면 일주일이 안되는 사이 제품 - [에이전트 세션을 핸드오프 해보기 #1](https://platanus.kr/post/4007) - Claude Code를 핸드폰에서 이어 쓰고 싶었을 뿐인데 누가 클로드 세션을 가지고 있을까? Claude Code 세션을 모바일로 넘겼다가 다시 개발 PC로 가져오려면 무엇이 필요한가. Orca와 Paseo를 구조부터 뜯어보고, Paseo가 만든 세션이 정말 native Claude Code로 돌아오는지 내 개발 PC에서 직접 확인했다. 나는 Warp + Claude Code로 개발하고 있다. 프로젝트 디렉터리로 가서 claude를 띄우고, 하다 만 작업은 - [누구나 이해하는 클라우드 인프라 지식사전 - 책소개](https://platanus.kr/post/3997) - 플랫폼 엔지니어링으로 확장하기 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : バックエンドエンジニアのためのインフラ・クラウド大全 저자 : 馬場俊彰 바바 도시아키 출간 : SHOEISHA, 2025 / 한빛미디어, 2026 거의 대부분의 IT 개발 직렬이 소프트웨어와 코드로 제어가 가능한시대가 되었더라도 그 이면에는 변하지 않는 것들이 있다. 실제 세계의 운영 전략과 소프트웨어가 해줄 수 없는 테크니컬 엔지니어링은 좀처럼 학교나 - [하네스 엔지니어링 with 클로드 코드 - 책 소개](https://platanus.kr/post/3988) - 도구에서 동료로 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 제목 : 하네스 엔지니어링 with 클로드코드 저자 : 황민호 출간 : 한빛미디어, 2026 AI를 사용해 결과를 만들어내는 과정이 더욱 견고해지고 있다. 이제 하나의 AI를 다루는것 보다 여러 AI에 역할을 부여해 모델을 결정론적으로 제어하는 소프트웨어 로직. 즉, 하네스 엔지니어링이라는 개념이 등장했다. 다소 추상적이고 최신의 내용을 - [백엔드 개발자 온보딩 가이드 - 책소개](https://platanus.kr/post/3975) - 모두에게 막막한 새로운 적응을 위하여 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 제목 : 백엔드 개발자 온보딩 가이드 저자 : 이준형, 김석현 출간 : 한빛미디어, 2026 신입이든 경력이든 온보딩 이후의 세계가 익숙한 사람은 없다. 동료들과의 협업이 필연적인 직무가 바로 개발이다. 수평, 수직적으로 얽힌 다양한 이해관계 속에서 조직의 목표를 향해 개발자의 역할을 다 해야 - [클라우드 애플리케이션 아키텍처 패턴 - 책 소개](https://platanus.kr/post/3961) - 진흙 덩어리에서 마이크로서비스까지, 70개의 패턴이 그리는 지도 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Cloud Application Architecture Patterns 저자 : Kyle Brown, Bobby Woolf, Joseph Yoder 출간 : O'Reilly Media, 2025 / 한빛미디어, 2026 추천사에 이런 문장이 있었다. "근본적으로 옮기기 쉬운 소프트웨어들은 이미 클라우드로 전환되었다. 따기 쉬운 열매는 이미 다 땄다." - [#1 나의 두번째 서비스 데뷔](https://platanus.kr/post/3739) - 돛단배 띄워서 박수받기 사람은 뭘 위해 사는 걸까. 잠자리에서 눈 비비고 일어나서 대충 씻고, 북적이는 대중교통에 몸 구겨넣고, 8시간 길면 12시간 버텨내고, 진 빠진 채로 집에 와서 다음 날 또 출근하기 위해 다시 잠자리에 몸 구겨넣기 위해 사는 걸까. 나는 그렇게 생각하고 싶지 않다. 21세기에는 즐길 것들이 너무 많다. 인터넷과 AI는 취미의 진입장벽을 낮췄고, 숏폼과 - [How throw null Happens - Contributing to Resilience4j](https://platanus.kr/post/3702) - Resilience4j에 NPE 버그픽스 기여한 이야기 Resilience4j Retry에서 throw null이 만들어지는 구조: 결과 기반 재시도와 인터럽트가 만났을 때 먼저 알아야 할 것 Resilience4j의 Retry는 재시도를 트리거하는 방식이 두 가지다. 첫 번째는 예외 기반 재시도. DB 커넥션이 끊기거나 타임아웃이 발생하면 예외가 던져지고, 라이브러리는 이걸 감지해서 재시도한다. 직관적이고, 대부분의 재시도가 이 경로를 탄다. 두 번째는 결과 기반 재시도 - [이것이 Spring AI다 개정판 - 책 소개](https://platanus.kr/post/3723) - Java 생태계에 올라간 강력한 AI 에이전트 통합 개발 방법 원제 : 이것이 Spring AI다 (개정판) 저자 : 신용권 출판 : 한빛미디어, 2026 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 지난달에 LangChain 기반으로 AI 에이전트를 만드는 책을 읽었다. 체인 구성, RAG, 메모리, MCP, 종합 프로젝트까지 한 호흡으로 따라가면서 에이전트가 대강 어떤 구조로 돌아가는지 감을 - [VPN 과 Split horizon DNS](https://platanus.kr/post/3669) - When VPN Meets Split-Horizon DNS OpenConnect SSL VPN을 구축하고 Cisco AnyConnect 클라이언트로 VPN을 운영하고 있다. 외부에서 내부망에 접속하기 위한 용도인데, VPN을 연결하면 내부 IP로는 모든 접근이 잘 되고 NAT를 통한 인터넷도 가능한데, 외부 접속용으로 만들어놓은 도메인들이 전부 먹통이 되는 현상이 있었다. 도메인만 안 되고 IP는 되는, 꽤 성가신 문제였다. 증상 정리 VPN 연결 후 상태는 - [AI 에이전트 마스터 클래스 - 책소개](https://platanus.kr/post/3648) - AI 에이전트 A to Z 원제 : AI 에이전트 마스터 클래스 저자 : 김구현 출판 : 한빛미디어, 2026 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 나는 백엔드 개발자로 활동하고 있지만, AI 시대에 힘입어 최근 이와 관련된 개발을 많이 하고 있다. 가장 최근에는 OpenStack MCP Server 에 참여했었고 그 외에 사내에서 AI 에이전트와 관련된 - [헤드퍼스트 소프트웨어 아키텍처 - 책 소개](https://platanus.kr/post/3608) - 실용적인 아키텍처 설계방법 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Head First Software Architecture 저자 : Raju Gandhi, Mark Richards, Neal Ford 출판 : 한빛미디어, 2025 / O'Reilly, 2024 소프트웨어 아키텍처란, 시스템의 구조를 정의하는 중요한 의사결정들의 집합이다. 단순히 컴포넌트를 나누거나, 흐름도를 그리는것이 아니라, 비즈니스 요구사항과 기술적 제약 사이에서 최적의 균형점을 찾는 과정입니다. 좋은 아키텍처는 - [소프트웨어 아키텍처 The Basics - 책 소개](https://platanus.kr/post/3622) - AI 시대의 소프트웨어 아키텍처 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Fundamentals of Software Architecture 2E 저자 : Mark Richards, Neal Ford 출판 : 한빛미디어, 2025 / O'Reilly, 2025 멋진 책이 돌아왔다. 초판도 많은 내용을 담고 있으나, AI 시대의 흐름에 따른 아키텍처 고려사항과 클라우드를 고려한 비용분석 내용이 추가되어 현행화를 이뤄냈다. 이번에는 - [Issue with httpd, php-fpm process failing to write files](https://platanus.kr/post/3617) - Apache랑 PHP-FPM 사이에서 /home이 read-only로 보이던 문제를 한 번 정리해봤다. 결론부터 말하면, 커널이나 LVM, ext4가 문제가 아니라 systemd httpd 서비스의 Protect 옵션들이 /home을 읽기 전용으로 바꿔놓고 있었다. 상황 정리 – CLI에선 되는데, 웹에서만 안 된다 워드프레스 마이그레이션 후 플러그인 업데이트를 누르니 FTP 자격 증명을 물어본다.권한 문제 같아서 퍼미션을 열어도 해결이 안 돼서, 직접 PHP로 쓰기 - [Guide to learning the Spring Framework Transaction](https://platanus.kr/post/3595) - 스프링 트랜잭션 가이드 스프링의 @Transactional 애노테이션 하나면 트랜잭션을 쉽게 다룰 수 있다고 생각했는데, 실무에서 쓰다 보니 생각보다 고려할 게 많았다.프록시가 어떻게 동작하는지, 전파 규칙은 어떻게 설정해야 하는지, JPA와는 어떻게 맞물리는지 등등...그래서 트랜잭션의 기본 개념부터 스프링이 내부적으로 어떻게 처리하는지까지, 실무에서 마주쳤던 내용들을 정리해봤다. 스프링 트랜잭션의 본질 개념과 목적 트랜잭션은 데이터베이스에서 데이터의 일관성과 원자성(Atomicity) 을 보장하기 위한 - [Guide to learning the OpenStack architecture](https://platanus.kr/post/3328) - 작년 입사와 동시에 팀 대상으로 혼자 진행했던 스터디 및 세미나 자료를 다시 한번 정리하여 공개한다. 오픈스택 컴포넌트 전부 메인 컴포넌트 : Nova, Glance, Swift, Cinder, Neutron, Horizon, Keystone 유효한 컴포넌트 : Ceph, Manila, Octavia, Masakari, Heat, Freezer, Ceilometer, Gnocchi, Placement 오픈스택의 메인 컴포넌트 및 유효한 컴포넌트 리스트 정리 메인 컴포넌트 오픈스택이 작동하기 위해 꼭 필요한 - [스프링 6 레시피 - 책 소개](https://platanus.kr/post/3560) - 스프링 프레임워크 쿡북 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Spring 6 Recipes : A Problem-Solution Approach to Spring Framework 저자 : Marten Deinum, Daniel Rubio, Josh Long 출판 : 한빛미디어, 2025 / Apress, 2023 3년을 서평 활동을 하면서 한번도 스프링이 메인 주제가 되는 책을 다룰 일이 없었는데 이번에 좋은 기회로 - [돌이켜 보면](https://platanus.kr/post/3550) - 래퍼 이센스의 첫번째 솔로 앨범 'The Anecdote' 가 발매 10주년을 맞이하여 Instrumental 트랙이 포함된 기념반이 발매되었다. 이 앨범은 한국 힙합 역사에서 큰 의미를 갖고 있고, 나아가 한국 음악사에서도 여러가지로 의미가 큰 앨범이다. 음악 외적으로는 한국 최초 '옥중앨범' 이라는 임팩트가 따라다니지만, 음악만 봐도 트랙 전체에서 그의 인생사, 가치관, 음악에 대한 태도 등을 날 것 그대로 엿볼 - [소프트웨어 아키텍처 101 - 책 소개](https://platanus.kr/post/1938) - 엔지니어링 접근 방식으로 배우는 소프트웨어 아키텍처 기초 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Fundamentals of Software Architecture 저자 : Mark Richards, Neal Ford O'Reilly Media, 2020 / 한빛미디어, 2021 서비스 구현이 고도화 되고 시스템이 복잡해지는 시대다. 소프트웨어 개발 생태계가 빠르게 발전함과 동시에 소프트웨어 아키텍트의 역할도 변화무쌍하고 범위도 넓어지고 있다. 이 - [아키텍트 첫걸음 - 책 소개](https://platanus.kr/post/3389) - 아키텍트로 성장하기 위한 실무 가이드 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 원제 : アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築 저자 : 米久保 剛 요네쿠보 다케시 출판 : 한빛미디어, 2025 / 翔泳社, 2024 아키텍트는 무슨 일을 할까? 프로젝트 설계? 코드 품질 유지? 현업 부서와 의사 결정? 일정 관리? '잘 만들기 위한' 아키텍처 기술서는 많이 있다. 3년 - [생성형 AI를 위한 프롬프트 엔지니어링 - 책 소개](https://platanus.kr/post/3361) - AI와 대화하는 법, 프롬프트로 배우다 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 원제 : Prompt Engineering for Generative AI: Future-Proof Inputs for Reliable AI Outputs 저자 : James Phoenix, Mike Taylor 출판 : 한빛미디어, 2025 / O'Reilly Media, 2024 AI 시대와 문맥 이제는 더이상 생성형 AI 를 사용하지 않는 사람들은 없다. 단순히 - [OpenStack 개발환경 설정](https://platanus.kr/post/3347) - 최소 개발환경 설정 mac, pyenv, cursor ai 환경 Python 가상환경 pyenv 설치 brew install pyenv echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc echo 'eval "$(pyenv init --path)"' >> ~/.zshrc echo 'eval "$(pyenv init -)"' >> ~/.zshrc source ~/.zshrc pyenv install 3.11 mkdir openstack-dev cd openstack-dev pyenv local 3.11 python -m venv OCA-OpenStack - [자바 최적화 2판 - 책 소개](https://platanus.kr/post/3341) - 자바, 느림의 미학을 파헤치다 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 원제 : Optimizing Cloud Native Java, 2E 저자 : Benjamin J. Evans, James Gough 출판 : 한빛미디어 2025 우리는 종종 자바를 “느린 언어”라고 여긴다. 무겁고, 메모리를 많이 잡아먹고, 성능을 확보하려면 많은 노력이 든다고. 하지만 그런 고정관념을 뒤흔들며, 자바 성능 문제의 본질을 - [Coding with MCP #1](https://platanus.kr/post/3322) - Python pyenv brew install pyenv echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc echo 'eval "$(pyenv init --path)"' >> ~/.zshrc echo 'eval "$(pyenv init -)"' >> ~/.zshrc source ~/.zshrc pyenv install 3.11 pyenv local 3.11 python -m venv .venv node.js nvm brew install nvm mkdir ~/.nvm echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc echo '[ - [Kubernetes Foundation #1](https://platanus.kr/post/3314) - kubectl Quick Reference nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.27-alpine ports: - containerPort: 80 resources: requests: cpu: "100m" memory: "64Mi" limits: cpu: "500m" memory: "64Mi" readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 - [Kubernetes cluster deployment guide](https://platanus.kr/post/3318) - kind Docker # docker (container) dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl --now enable docker Install kind # kind (kubernetes labs) dnf install golang -y go install sigs.k8s.io/kind@v0.27.0 echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc source ~/.bashrc # kubectl VERSION=$(curl -Ls https://dl.k8s.io/release/stable.txt) curl -LO "https://dl.k8s.io/release/${VERSION}/bin/linux/amd64/kubectl" chmod +x kubectl sudo mv kubectl - [Kubernetes Foundation #2](https://platanus.kr/post/3320) - 실습 환경 구성에 kind 활용할것 HPA (Horizontal Pod Scaler) https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/https://kubernetes.io/docs/reference/kubectl/generated/kubectl_autoscale/ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: apache-serevr namespace: autoscale spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: apache-serevr minReplicas: 1 maxReplicas: 4 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 behavior: scaleDown: stabilizationWindowSeconds: 30 만약 명령어로 한다면.. kubectl autoscale deployment apache-server \ - [개발자 기술면접 노트 개정판 - 책 소개](https://platanus.kr/post/3305) - 불확실성을 걷어낼 때 까지 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 저자 : 이남희 출판 : 한빛미디어, 2025 오늘날 개발자는 과잉공급이다. 신입 공채는 문을 닫은지 오래고, 변별력을 위해 존재하는 채용 프로세스는 더 견고해지고 복잡해졌다. 주변에서 들리는 고용불안, 구직 실패는 더 이상 남의 이야기가 아니게 되었다. 그렇다고 과거보다 복잡해진 비즈니스와 아키텍처를 두고 기업들은 - [스프링 프레임워크와 파일 업로드 릴레이](https://platanus.kr/post/3253) - 파일 업로드 다운로드를 개발하다 보면 내가 개발하고 있는 어플리케이션이 파일이 저장되는 종착지가 아닐때가 있다. 예를들어 하나의 백엔드 어플리케이션이 모든 도메인을 처리하고 있고 그중에 파일 관련된 핸들링도 포함되어있다면 그 백엔드가 파일 시스템 어딘가에 저장하거나 S3 스토리지로 보낸다. 그런데 마이크로서비스가 보편화된 시대에서 파일이 여러 서비스를 거쳐야 파일 핸들링을 하는 서비스에 도달하는 경우가 있을 수 있다. 그 역할을 - [Spring WebFlux vs Spring MVC](https://platanus.kr/post/2133) - WebFlux는 기존의 Spring MVC와 무엇이 다른가? 웹 어플리케이션을 위한 Spring MVC (블로킹)과 Spring WebFlux(넌블로킹) 방식이 있음 물론 Spring MVC안에서도 @Async 어노테이션으로 비동기 처리를 활성 할 수 있으나 Filter, Interceptor 자체가 동기 처리라 엄청난 성능 향상은 없음 Spring WebFlux에도 Spring MVC와 마찬가지로 @Controller 어노테이션이 있있음. Spring MVC와 큰 차이라면 스트림을 위해 반환에 Mono, Flux를 사용. Spring - [Spring Boot; 훑어보기#1](https://platanus.kr/post/808) - 시작하기 전에 사족 나의 스프링 역사는 작년 이맘때쯤 시작됐다. (2020년 2월) 백엔드 개발자가 되기 위해 호기롭게 한권의 책으로 시작했으나 당시 나한텐 자바 언어를 떠나서 OOP에 대한 지식이 없었다. 세상에 프로그래밍을 위한 책이 모두 완벽하면 좋겠으나 다른 분야의 책들도 정오표를 내는 마당에 사전 지식없이 오류에 부딪히기엔 너무 버거웠다. 책 앞부분 부터 예제의 오류로 대부분의 시간을 보내다가 - [Spring Boot; 훑어보기#2 - GetMapping, PostMapping](https://platanus.kr/post/838) - @GetMapping, @PostMapping 사용법 @GetMapping("/members/new") public String createForm() { return "members/createMemberForm"; } @PostMapping("/members/new") public String create(MemberForm form) { Member member = new Member(); member.setName(form.getName()); memberService.join(member); return "redirect:/"; } URI를 매핑하고 템플릿으로 반환한다. (String) 이름 등록 - [Spring Boot; 훑어보기#3 - JDBCTemplate](https://platanus.kr/post/842) - Spring 데이터 억세스 H2 데이터베이스 순수 JDBC 스프링 JdbcTemplate : JDBC 중복을 제거해서 만든 템플릿 JPA : 객체를 쿼리 없이 DB에 저장하는 방법 스프링 데이터 JPA : JPA를 간단하게 쓰기 위한 스프링의 Wrapping H2 데이터베이스 official site bin/h2.sh 실행 JDBC 간단한 정리 Connection 객체 : DB연결 객체 PreparedStatement 객체 : 쿼리와 코드를 매칭해준다. ResultSet 객체 - [Spring Boot; 훑어보기#4 - JPA](https://platanus.kr/post/844) - 2021-02-16 — JPA (Java Persistent API) JPA → 인터페이스 (자바 표준) hibernate → 구현체 (여러 벤더들이 있음) 쿼리도 JPA가 직접 만들어서 실행해준다. 객체를 메모리에 넣듯 DB에 넣을 수 있게 해준다. SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환할 수 있다. build.gradle implementation 'org.springframework.boot:spring-boot-starter-data-jpa' application.properties spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none spring.jpa.show-sql: JPA가 날리는 쿼리를 볼 수 있다. spring.jpa.hibernate.ddl-auto: 테이블을 자동으로 - [Spring Boot; 훑어보기#5 - Spring Data JPA](https://platanus.kr/post/847) - 2021-02-17 — 스프링 데이터 JPA 구현체 없이 인터페이스만으로 리포지토리에 커밋이 가능한 코드를 만들 수 있다. 반복적으로 개발한 CRUD 기능도 스프링 데이터 JPA가 모두 제공한다. RDB에서 스프링 데이터 JPA는 아주 좋은 기능이다. 스프링 데이터 JPA 인터페이스 public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository { @Override Optional findByName(String name); } 이외의 인터페이스 선언이나 구현체는 필요없다. 인터페이스 이름에 규칙이 있다. - [Spring Boot; Logback, Log4JDBC 개요](https://platanus.kr/post/1077) - 2021-03-04 — Logback Log4j : 자바의 예외를 처리하기 위해 시작된 프로젝트 (종료) fork → Logback slf4j(Simple Logging Facade for Java) 와 함께 사용함 slf4j : 로깅 모듈 Interface slf4j를 이용해 코드를 작성하고 내부적으로 Logback, log4j2로 작동 Logback 설정 %d %5p [%c] %m%n - [Spring Boot; Transactional](https://platanus.kr/post/1086) - 2021-03-04 — 부트에서의 트랜잭션 코드 기반의 트랜잭션, 어노테이션을 통한 선언적 트랜잭션 두가지를 지원한다. // DatabaseConfiguration.class //... @EnableTransactionManagement public class DatabaseConfiguration { //.. @Bean public PlatformTransactionManager transactionManager() throws Exception { return new DataSourceTransactionManager(dataSource()); } //.. @EnableTransactionManagement : 어노테이션 기반의 트랜잭션 활성화. PlatformTransactionManager : 스프링이 제공하는 트랜잭션 매니져 등록. //BoardServiceImplement.class @Service @Transactional public class BoardServiceImplement implements BoardService { @Transactional - [Spring Boot; Interceptor](https://platanus.kr/post/1081) - 2021-03-04 — Interceptor 스프링의 인터셉터는 어떤 URI를 호출했을 때 요청 컨트롤러가 처리되기 전 또는 후 작업을 하기 위해 사용 된다 (프록시 패턴) 이런 역할은 Filter와 Interceptor로 수행할 수 있다. Spring의 MVC 요청 lifecycle 위치 filter는 dispatcher servlet 앞 단에서 동작 interceptor는 handler로 가기 전 동작 제어권 filter는 servlet의 일부 기능이다. interceptor는 spring framework내에 있기 때문에 bean을 사용할 - [Spring Boot; AOP](https://platanus.kr/post/1084) - 2021-03-04 — 부트에서의 AOP 스프링 부트에서의 AOP도 역시 마찬가지로 적용할 수 있다. slf4j 로깅을 aspect로 등록하는 코드. // webboard.aop.LoggerAspect.class @Component @Aspect @Slf4j public class LoggerAspect { @Around("execution(* org.platanus.webappboard..controller.*Controller.*(..)) or" + "execution(* org.platanus.webappboard..service.*Implement.*(..)) or" + "execution(* org.platanus.webappboard..dao.*Mapper.*(..))") public Object logPoint(ProceedingJoinPoint joinPoint) throws Throwable { String type = ""; String name = joinPoint.getSignature().getDeclaringTypeName(); if (name.indexOf("Controller") > -1) { type - [Spring Boot; Exception](https://platanus.kr/post/1109) - 2021-03-04 — 부트에서 예외처리 아래의 3가지 방법이 있다. 자바의 방법 : try/catch 사용 컨트롤러 단위 : 각각의 컨트롤러에서 @ExceptionHandler 사용 전역 처리 : @ControllerAdvice을 사용한 전역 예외처리 @ExceptionHandler는 중복코드가 발생한다고 한다.. 여기서 나올 중복 코드가 그 중복이 아닐텐데.. @ControllerAdvice 스프링 3.2에서 추가됨. Annotation만으로 추가 설정없이 예외 처리 가능. @ControllerAdvice @Slf4j public class ExceptionHandler { @org.springframework.web.bind.annotation.ExceptionHandler(Exception.class) public ModelAndView - [commons-io로 구현하는 Multipart](https://platanus.kr/post/1111) - 2021-03-26 — 관리 차원에서 후속편 안내 이 글 역시 이 블로그에서 꾸준히 인기가 좋아 commons-io가 아닌 스프링 multipart를 사용한 파일 업로드 기능을 다시 정리해서 올려봤다. 업로드와 다운로드 두편으로 나눠서 올라가고 우선 업로드편 링크를 남긴다. 👉 스프링 부트 Multipart 업로드편 파일 업로드와 다운로드에서 고려해야 할 부분 첨부파일의 유효성 검사 파일 전송의 진행률 표시 예외처리 사용자 편의성의 드래그 앤 - [스프링 부트에서 RESTful](https://platanus.kr/post/1114) - 2021-03-26 — RESTful 게시판으로 변경하기 Controller //... @RequestMapping(value = "/board/write", method = RequestMethod.GET) public String openBoardWrite() throws Exception { return "/board/restBoardWrite"; } @RequestMapping(value = "/board/write", method = RequestMethod.POST) public String insertBoard( BoardDto board, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception { boardService.insertBoard(board, multipartHttpServletRequest); return "redirect:/board"; } //... 두 요청의 mapping이 주소가 같으나 RequestMethod가 GET과 POST로 구분 되는것을 알 수 있다. - [Redis를 RDB처럼 쓰려고 했던 시도](https://platanus.kr/post/2163) - 🫠 실패에 대한 짧은 결론 : 레디스는 인메모리 DB로써 빠른 IO를 요구하는 작업에 최적화 되어있다. 예를 들면 세션 클러스터링이나 캐싱에 많이 사용된다. 그러나 Entity를 계층 구조로 만들고 깊은 내부의 있는 필드에 Document나 RDB 하듯 LIKE 쿼리를 구현하는 것은 바람직하지 않아보인다. 물론 단순한 구조의 Entity에 id필드를 지정하고 id를 가지고 직렬화/역직렬화 하는 것은 가능하다. 결론적으로 key로 value에 - [스프링 부트에서 Multipart - 업로드편](https://platanus.kr/post/2175) - 시작에 앞서서.. 이번에도 전편의 인기에 의해 불려나온 후속편이다. 지난번 아무것도 모르던 시절, 아파치의 commons-io 를 활용해 CommonsMultipartResolver 로 구현했다. 이번에는 스프링의 MultipartFile 를 이용해 파일 업로드 기능을 구현해보겠다 (현재 개인 프로젝트에 이 방식을 사용중) 아울러 김영한 강사님의 스프링 MVC 강의에 이같은 내용이 많기 때문에 이번에는 파일을 서빙하고 저장하고 관리되는 관점에서 글을 더 풀어보겠다. 이 글을 - [스프링 부트에서 Multipart - 다운로드편](https://platanus.kr/post/2188) - 1편의 업로드 기능을 구현했다면 2편에서는 다운로드를 위한 Controller 와 리소스를 가지고오는 부분에 대해서 설명하겠다. 전편에서 업로드를 구현하기 위해 Multipart 를 사용했다면 이번 편에서는 파일 식별자로 어떻게 파일을 특정하고 응답으로 파일을 내려줄 수 있는지 구현해본다. 다운로드 바이너리는 org.springframework.core.io.Resource 를 통해 응답을 내려주는것이 특징이다. 컨트롤러부터 보자. 컨트롤러에서 파일을 내려 줄 때 두가지 유형이 있다. 웹 브라우저에서 다운로드 - [그림으로 배우는 도커 - 책 소개](https://platanus.kr/post/3241) - 컨테이너로 실제 어플리케이션 실행 환경 만들기 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 리눅스 컨테이너는 컴퓨팅 가상화 같은 인프라 리소스를 비롯해 어플리케이션 빌드 및 배포 방식과 라이프사이클 그리고 서비스 운영환경도 바꿔놨다. 어플리케이션이 컨테이너 단위로 패키징 되기 시작하면서 서비스에 유연함이 더해졌고 이것이 발전해 현재의 컨테이너 오케스트레이션 세상까지 도달했다. 이러한 상황속에서 개발자는 자신의 어플리케이션을 - [얼마나 한 조직에 오래 있어야 할까?](https://platanus.kr/post/3229) - 지난해 발간되어 많은 인기가 있었던 '면접의 질문들 (김형식 저)' 책의 일부분이다. 기대를 많이 하고 봤는데 직장생활 좀 한 사람이면 잘 아는 내용들의 나열이다. '평소 태도를 바르게 하고 본인이 처한 상황에 대해서 객관화 해라.' 이 책을 한마디로 정리하자면 그렇다. 그래서 인터뷰 자체 또는 인터뷰어에 대한 인사이트가 목적이라면 별로 추천하고 싶지 않지만… 이 꼭지는 커리어에 대한 여러 - [자바 코드의 품질을 높이는 100가지 방법 - 책 소개](https://platanus.kr/post/3231) - 한번은 마주쳐본 문제들에 대한 자바 언어 스팩의 심도있는 분석 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 원제 : Grokking Algorithms, Second Edition 저자 : Aditya Y Bhargava 출판 : 한빛미디어, 2025 / Manning Publication, 2024 Java는 명실상부 OOP를 대표하는 프로그래밍 언어다. 특히 이 언어를 사용하여 만들어진 Spring framework 는 대규모 백엔드 어플리케이션을 - [그로킹 알고리즘 - 책 소개](https://platanus.kr/post/3223) - 첫 만남이 중요한 알고리즘 한빛미디어 서평단 활동을 위해서 책을 협찬 받아 작성된 서평입니다. 원제 : Grokking Algorithms, Second Edition 저자 : Aditya Y Bhargava 출판 : 한빛미디어, 2025 / Manning Publication, 2024 알고리즘은 프로그래밍에서 빼놓을 수 없는 영역이다. 방대한 자료를 분석하고 요구사항에 맞는 해법을 내놓는데 최적의 해결방안을 내놓는데 필요한 것이 바로 알고리즘이다. 최적의 해결방안을 - [객체에서 함수로 - 책 소개](https://platanus.kr/post/3218) - 함수형 프로그래밍을 제대로 길벗에서 책을 제공받아 자유롭게 작성된 서평입니다. 원제 : From Objects to Functions: Build Your Software Faster and Safer with Functional Programming and Kotlin 저자 : Uberto Barbini 출간 : 길벗, 2024 / Pragmatic Programmers, 2023 함수형 프로그래밍은 순수 함수라는 뜻으로 참조 투명성을 통해 변하지 않는 결과값을 도출하면서 내부 가시성을 최소화 하고, 함수를 - [Do it! 자바 프로그래밍 입문 개정판 - 책 소개](https://platanus.kr/post/3212) - 이지스퍼블리싱에서 책을 제공받아 자유롭게 작성된 서평입니다. 저자 : 박은종 출간 : 이지스퍼블리싱, 2024 프로그래밍 언어는 많은것들을 가능하게 한다. 몇 가지 문법과 메소드와 컴파일과 인터프리터가 갖추어지면 그 법칙 속에서 짜여진 코드라는 글자를 통해 비서, 도구, 나만의 세상, 나아가 직업으로도 활동할 수 있는 수단으로 매우 매력적인 언어다. 세상에 수 많은 언어가 있고, 역사가 있으며, 유행도 있으며 오늘날에도 - [2024 4Q 분기정리](https://platanus.kr/post/3202) - 4Q 활동정리 무엇을 했는가 한 분기에 4가지가 동시에 돌아갔다. 기술 검증 피쳐 개발 레거시 코드 파먹기 차세대 설계 및 개발 벌려놓은 일 건강 챙기기 건강 만들기 건강 하기 생각 변화 마지막이니 생각의 변화 보다는 오랫동안 그렇다고 믿어왔고 경험이 증명하는 가치 몇 가지를 적어본다. 다른 사람한테 '이렇게 살아라-' 훈계 보다는.. 어느날에 내가 잘 흘러가게 되는 날이 - [소플의 처음만난 AWS - 책 소개](https://platanus.kr/post/3192) - 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 저자 : 이인제 출간 : 한빛미디어, 2024 막연히 클라우드 플랫폼을 마주쳤을때 어떤 기능을 사용할 수 있는지, 내 노트북에서 실행 가능했던 어플리케이션을 어떻게 배포할지 막막해진다. 또한 2024년 기준으로 컴퓨팅, 스토리지, 네트워킹 외에도 CDN, 서버리스, 관측가능성 등 시나리오나 학습 없이는 잘 활용하기 어려운 기능들도 있다. 그래서 아는 기능만 - [오브젝트; 동적 메서드 탐색과 다형성](https://platanus.kr/post/3180) - 동적 메서드 탐색과 다형성 객체지향 언어가 제공하는 업캐스팅과 동적 바인딩을 이용하면 부모 클래스 참조에 대한 메시지 전송을 자식 클래스에 대한 메서드 호출로 변환할 수 있다. 객체지향 시스템은 다음 규칙에 따라 실행할 메서드를 선택한다. 메시지를 수신한 객체는 먼저 자신을 생성한 클래스에 적합한 메서드가 존재하는지 검사하낟. 존재하면 메서드를 실행하고 탐색을 종료한다. 메서드를 찾지 못했다면 부모 클래스에서 메서드 - [소프트웨어 엔지니어 가이드북 - 책 소개](https://platanus.kr/post/3170) - 가야할 방향 찾기 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : The Software Engineer's Guidebook: Navigating senior, tech lead, and staff engineer positions at tech companies and startups 저자 : Gergely Orosz 출간 : Pragmatic Engineer BV, 2023 / 한빛미디어, 2024 일반적으로 부르는 개발자라는 직군은 이 나라를 대표하는 직업 중 빠질 수 - [오브젝트; 업캐스팅과 동적 바인딩](https://platanus.kr/post/3162) - 업캐스팅과 동적 바인딩 같은 메시지, 다른 메서드 실행 시점에 메서드를 탐색하는 과정을 살펴보자. public class Professor { private String name; private Lecture lecture; public Professor(String name, Lecture lecture) { this.name = name; this.lecture = lecture; } public String compileStatistics() { return String.format("[%s] %s - Avg: %.1f", name, lecture.evaluate(), lecture.average()); } } 다음은 다익스트라 교수가 강의하는 - [2024 3Q 분기정리](https://platanus.kr/post/3146) - 3Q 활동정리 이벤트 생성 중단 무엇을 했는가 '제대로 된 삶'을 살기 2 OpenInfra Summit Asia 참관 한빛미디어 서평활동 3개월 연속 우수리뷰 달성 '제대로 된 삶'을 살기 2 오래전부터 예정되어 있거나 당장 해야 하는 일을 제외하고 새로운 시도나 습득에 대해서 멈췄다. 당분간은 이벤트를 그만 만들어야 한다고 직감이 경고한다. 플라이바이 하는 그때를 위하여. OpenInfra Summit Asia 참관 - [Java; Class](https://platanus.kr/post/1467) - 2021-05-21 — Object class java.lang 패키지 java.lang.*은 컴파일 할때 자동으로 추가된다. 모든 클래스의 최상위 클래스 Object Object클래스는 모든 자바 클래스의 최상위 클래스다. 모든 클래스는 Object 클래스로부터 상속을 받는다. 클래스를 만들때 extends Object를 하지 않지만, 컴파일 과정에서 자동으로 들어간다. 모든 클래스가 Object 클래스를 상속 받았으므로 Object의 메소드를 사용할 수 있고 재정의 할 수도 있다 주로 사용되는 Object클래스의 메소드 - [오브젝트; 상속을 합성으로 바꾸기](https://platanus.kr/post/3065) - 합성 관계로 변경하기 컴파일 타임 관계를 런타임 관계로 변경함으로써 이 문제를 해결한다. 이것이 합성이다. 상속을 사용하는 것은 컴파일 타임의 의존성과 런타임의 의존성을 동일하게 만들겠다고 선언하는 것이다. 그래서 상속을 사용하면 부모 클래스와 자식 클래스 사이의 관계가 정적으로 고정되기 때문에 실행 시점에 동적으로 관계를 변경할 수 있는 방법이 없다. 합성을 사용하면 구현 시점에 정책들의 관계를 고정시킬 필요가 - [오브젝트; 상속과 다형성](https://platanus.kr/post/3158) - 코드 재사용을 목적으로 상속을 사용하면 변경이 어렵고 유연하지 못한 설계에 이른다. 상속은 타입 계층을 구조화하기 위해 사용해야 한다. 타입 계층은 다형성의 기반을 제공한다. 상속은 인스턴스를 동일하게 행동하는 그룹으로 묶기 위한 관점으로 사용되어야 한다. 다형성 다형성 Polymorphism은 많은 형태를 가질 수 있는 능력을 의미한다. 컴퓨터 과학에서 다형성은 하나의 추상 인터페이스에 대해 코드를 작성하고 이 추상 인터페이스에 - [쿠버네티스 창시자에게 배우는 모범사례 2판 - 책 소개](https://platanus.kr/post/3073) - 쿠버네티스 '쿡북' 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Kubernetes Best Practices 2E 저자 : Brendan Burns 외 3인 출간 : O’Reilly Media, 2024 / 한빛미디어, 2024 이 책은 한마디로 쿠버네티스 환경에서의 운영을 데브옵스 엔지니어가 수행할만한 내용들로 모아놓은 사례집이다. 어플리케이션을 안정적으로 운영하기 위해 메트릭, 보안, CI/CD, 형상관리, 테스트, 롤링, 리소스 관리, 스테이징, 네트워킹, 멀티클러스터, 스토리지와 같은 주제에서 - [소프트웨어 설계의 정석 - 책 소개](https://platanus.kr/post/2420) - 개발자로서 한 걸음 더 내딛기 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : はじめての設計をやり抜くための本 第2版 (처음 설계를 시작하는 사람들을 위한 책 제2판) 저자 : 吉原 庄三郎 출간 : 翔泳社, 2022 / 한빛미디어, 2024 설계라는 영역의 세부 분야에 대해서 다루는 책은 많다, 아키텍처, UML, RDB 설계, 각종 개발 방법론, 프레임워크 개론 등, 제목만 붙여도 생각나는 책들이 많이 있다. 그러나 - [실무로 통하는 클린 코드 - 책 소개](https://platanus.kr/post/2419) - 깊이를 더하는 지름길 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Clean Code Cookbook 저자 : Maximiliano Contieri 출간 : O’Reilly Media, 2023 / 한빛미디어, 2024 백엔드 엔지니어를 위한 좋은 지침서들이 여럿 있다. 로버트 C 마틴의 클린 코드와 클린 아키텍처, 마틴 파울러의 리팩터링, 에릭에반스의 도메인 주도 설계를 비롯해 많은 책들이 있다. 나아가 백엔드에서 많이 사용되는 - [처음 시작하는 FastAPI - 책 소개](https://platanus.kr/post/2416) - 빠르게 시작하는 웹 프레임워크 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : FastAPI: Modern Python Web Development 저자 : Bill Lubanovic 출간 : O'Reilly Media, 2023 / 한빛미디어, 2024 웹 서비스를 구성하는 요소 중에 비즈니스 요구사항을 처리하고, 데이터의 가공과 저장을 하고, 보안의 위협에서 적절한 조치를 해야하는 백엔드 어플리케이션은 없어서는 안되는 요소다. 웹 - [오브젝트; 상속의 문제](https://platanus.kr/post/3058) - 객체지향 프로그래밍에서 코드를 재사용하기 위한 기법으로 상속과 합성은 가장 널리 사용된다. 상속 부모클래스와 자식클래스를 연결해 부모클래스의 코드를 재사용한다. 클래스 사이의 의존성은 컴파일 타임에 결정된다. is-a 관계 상속을 제대로 사용하기 위해서는 부모의 내부 구현을 상세하게 알아야 하기 때문에 결합도가 높음 정적인 관계 합성 전체를 표현하는 객체가 부분을 표현하는 객체를 포함해 부분 객체의 코드를 재사용한다. 객체 사이의 - [2024 2Q 분기정리](https://platanus.kr/post/3056) - 2Q 활동정리 남들 평생 한번 겪을까 말까 하는 큰 일들이 한 분기 안에 다 일어나서 이번 정리는 짧게 하려고 한다. 작년엔 오토바이 몇 대가 치고 가더니, 올해는 짐 가득 실은 덤프트럭 여러대가 나를 깔아 뭉게고 갔습니다. 추스리는 중. 좋은 사람이란 무엇인가에 대해 나름대로 결론을 얻었습니다. 일련의 사건들과 별개로 이젠 참는 것을 완전히 그만 두게 되었습니다. - [Java 메소드 오버라이딩과 가변인자](https://platanus.kr/post/2966) - 가변인자'만' 있는 시그니처 class Math { long add(int... args) { //... } } class MathTest { public static void main(String[] args) { Math math = new Math(); math.add(new int[]{1,2}); // Okay math.add(); // Okay } } 가변인자'도' 있는 시그니처 class Math { long add(long start, long end, int... args) { //... } } class MathTest - [오브젝트; 추상화에 의존하는 상속](https://platanus.kr/post/2774) - 취약한 기반 클래스 문제 부모 클래스의 변경에 의해 자식 클래스가 영향을 받는 현상을 취약한 기반 클래스 문제 라고 부른다. 이제 결합도의 개념을 상속에 적용해보자. 구현을 상속한 경우(extends) 파생 클래스는 기반 클래스에 강하게 결합되며, 이 둘 사이의 밀접한 연결은 바람직하지 않다. 설계자들은 이런 현상에 대해 "취약한 기반 클래스 문제"라는 명칭을 붙였다. 겉으로 보기에는 안전한 방식으로 클래스를 - [오브젝트; 상속과 중복 코드](https://platanus.kr/post/2768) - 객체지향 프로그래밍의 장점 중 하나는 코드의 재사용이다. 객체지향은 코드를 재사용 하기 위해 새로운 코드를 추가한다. 객체지향에서 클래스를 재사용 하는 전통적인 방법은 클래스를 추가하는 것이다. 이 장에서는 클래스를 재사용하기 위해 클래스를 추가하는 대표적인 방법인 상속에 관한 내용이다. 상속 외에도 새로운 클래스의 인스턴스 내에 기존 클래스의 인스턴스를 포함시키는 합성이라는 방법도 있다. 상속과 중복 코드 중복 코드를 제거해야 - [오브젝트; 의존성 주입과 의존 역전](https://platanus.kr/post/2452) - 의존성 주입 의존성 주입 Dependency Injection : 사용하는 객체가 아닌 외부의 독립적인 객체가 인스턴스를 생성한 후 이를 전달해서 의존성을 해결하는 방법 의존성 주입 기법 생성자 주입 Setter 주입 메서드 주입 숨겨진 의존성은 나쁘다 SERVICE LOCATOR 패턴 서비스를 사용하는 코드로부터 서비스가 누구인지 (서비스를 구현한 구체 클래스의 타입이 무엇인지), 어디에 있는지(클래스 인스턴스를 어떻게 얻을지)를 몰라도 되게 해준다. - [오브젝트; 개방-폐쇄 원칙](https://platanus.kr/post/2450) - 개방-폐쇄 원칙 개방 폐쇄 원칙 Open-Closed Principle : 소프트웨어 개체 (클래스, 모듈, 함수) 는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. 이는 다음의 관점을 반영한다. 확장 -> 동작확장에 대해 열려 있다 : 어플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 동작을 추가해서 어플리케이션의 기능을 확장할 수 있다. 수정 -> 코드수정에 대해 닫혀 - [데브옵스 엔지니어를 위한 실전 관찰 가능성 엔지니어링 - 책 소개](https://platanus.kr/post/2415) - 서비스를 넘나드는 관찰 가능성으로. 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Observability Engineering 저자 : Charity Majors, Liz Fong-Jones, George Miranda 출간 : O'Reilly Media, 2022 / 한빛미디어, 2024 프로덕트 운영을 하다 보면 서비스 품질을 유지하기 위해 항상 모니터링 알람에 신경을 써야 할때가 많다. 그러나 대부분의 모니터링은 사고가 먼저 있고 그로 - [켄트 벡의 Tidy First? - 책 소개](https://platanus.kr/post/2412) - 코드는 언제 정리해야해? 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Tidy First?: A Personal Exercise in Empirical Software Design 저자 : Kent Beck 출간 : O'Reilly Media, 2023 / 한빛미디어, 2024 익스트림 프로그래밍 XP 의 창시자이자 애자일 개발론, TDD 를 주장하는 켄트 벡의 새로운 책이다. Tidy First? 는 방법론이나 기술적인 맥락 - [함수형 프로그래밍 with 자바 - 책소개](https://platanus.kr/post/2411) - JVM은 함수형 프로그래밍을 어떻게 지원하는가? 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : A Functional Approach to Java: Augmenting Object-Oriented Java Code with Functional Principles 저자 : Ben Weidig 출간 : O'Reilly Media, 2023 / 한빛미디어, 2024 모던한 언어들의 대세에 따라 함수형 프로그래밍이 떠오르면서 'Java 에서의 함수형 프로그래밍' 에 대해서도 적지 않은 - [HA 연결지점의 상태 가져오기 - HAProxy Data Plane API](https://platanus.kr/post/2968) - 개요 HAProxy를 HA 기능 또는 리버스 프록시 용도의 gateway로 사용하고 있다면 하위의 master와 slave 노드들의 모든 상태를 REST API로 추출할 수 있다. 이것은 어플리케이션의 health check api 뿐만 아니라 TCP, SSH, HTTP 등 다양한 프로토콜에도 대응하기 때문에 특정 프로토콜에 의존적이지 않다. 또한 HAProxy에 하위 프로세스만 띄우는 형식이라 설정이 번잡하지 않고, 모든 노드를 알고 있는 HAProxy를 - [2024 1Q 분기정리](https://platanus.kr/post/2674) - 1Q 활동정리 사람 답게 살기 시작함익숙한 도메인의 깊이가 요구되는 엔지니어링 무엇을 했는가 이직 3개월 수습에서 정직원 전환 완료 하여 이직 최종 확정. 대기업빅테크유니콘 정리해고임금삭감구조조정 시대에 경력이직 성공을 축하하는 부분. 👏 '제대로 된 삶'을 살기 6시 to 2시 생활 그만 두니까 좀비에서 다시 사람 비스무리한 것이 되는 중. 건강한 조직 문화의 제대로된 동료들과 행복한 생활하는 중 - [Reflection; Public constructor](https://platanus.kr/post/2813) - Constructor 클래스 및 객체 생성 Constructor Java 클래스의 생성자는 제네릭 클래스인 Constructor 의 인스턴스로 나타낸다 이 객체는 클래스 생성자의 모든 정보를 포함하고 있다. 파라미터의 수 파라미터의 타입 클래스에는 여러개의 생성자가 있을 수 있다. Constructor 메소드 Class.getDeclaredConstructos() : 클래스의 모든 생성자를 반환한다. public이거나 아니거나 상관없이 모두 반환한다. Class.getConstructors() : Public 생성자만 반환한다. 특정 생성자 매개변수 유형을 - [오브젝트; 추상화에 의존하기](https://platanus.kr/post/2431) - 유연한 설계 의존성과 결합도 모든 의존성이 나쁜것은 아니다.의존성은 객체들의 협력을 가능하게 만드는 매개체라는 관점에서 자연스러운 것. 바람직한 의존성 = 재사용성 어떤 의존성이 다양한 환경에서 클래스를 재사용할 수 없도록 제한한다면 그 의존성은 바람직하지 못한 것. 즉, 컨텍스트에 독립적인 의존성은 바람직하다. 의존성에 대한 정도 = 결합도 (약한 결합도, 강한 결합도) 의존성과 결합도 일반적으로 의존성과 결합도를 동의어로 사용하지만 - [Reflection; Class Object](https://platanus.kr/post/2809) - Java Reflection 이 뭐지? JVM 기능 런타임 동안 클래스와 객체 정보를 추출할 수 있음 Reflection API로 접근 가능 JDK에 포함된 클래스 집합 Reflection이 할 수 있는 것 소스 코드를 수정하지 않고 새로운 프로그램 순서를 만들 수 있음. 실행하고 있는 클래스와 객체에 동적으로 코드 삽입. 실제로 사용하는 곳 로깅 프레임워크 ORM Spring Framework JUnit Jackson Spring - [오브젝트; GRASP와 책임 할당하기](https://platanus.kr/post/2330) - 데이터를 먼저 결정하고 고립된 객체의 상태에 초점을 맞추면 캡슐화를 위반하기 쉽고, 요소들 사이의 결합도가 높아지며, 코드를 변경하기 어려워진다. 책임에 초점을 맞춰서 설계할 때 어떤 객체에게 어떤 책임을 할당할지를 결정 하는 것이 어렵다. 책임 할당 과정은 트레이드오프 활동이다. 책임 주도 설계를 향해 데이터 중심의 설계에서 책임 중심의 설계로 전환하는 방법 데이터보다 행동을 먼저 결정하라 클라이언트 관점에서 - [오브젝트; 의존성과 전이](https://platanus.kr/post/2429) - 작고 응집도 높은 객체란 책임의 초점이 명확하고 한가지 일만 잘 하는 객체를 의미한다. 작은 객체들은 단독으로 수행할 수 있는 작업이 거의 없기 때문에 기능을 구현하기 위해 다른 객체와 협력해야 한다. 그러나 과도한 협력은 다른 객체에 대해 의존하게 된다. 객체지향 설계는 의존성을 관리하는 것이다. 또한 객체가 변화를 받아들일 수 있게 의존성을 정리하는 기술이다. 의존성 이해하기 변경과 - [오브젝트; 절차 추상화와 타입 추상화](https://platanus.kr/post/2408) - 데이터 추상화와 추상 데이터 타입 추상 데이터 타입 타입 : 변수에 저장할 수 있는 내용물의 종류와 변수에 적용될 수 있는 연산의 가짓수를 의미. 안타깝게도 프로시저만으로는 충분히 풍부한 추상화의 어휘집을 제공할 수 없다. 이것은 언어 설계에서 가장 중요한 추상 데이터 타입의 개념으로 우리를 인도한다. 추상 데이터 타입은 추상 객체의 클래스를 정의한 것으로 추상 객체에 사용할 수 - [오브젝트; 하향식 기능 분해](https://platanus.kr/post/2391) - STM LTM 인지 과부하 추상화 분해 프로시저 추상화와 데이터 추상화 시스템을 분해하는 방법 프로시저 추상화 Procedure abstraction : 소프트웨어가 무엇을 해야 하는지 추상화 기능 분해 Functional decomposition 또는 알고리즘 분해 Algorithm decomposition 데이터 추상화 Data abstraction : 소프트웨어가 무엇을 알아야 하는지 추상화 데이터를 중심으로 타입을 추상화 Type abstraction : 추상 데이터 타입 Abstract data type - [암호화 된 사설 SSL 인증서 만들기](https://platanus.kr/post/2334) - Self-signed public certificate with encrypted private key 만드는 방법 그냥 RSA 개인키를 만든다. 그 RSA 개인키를 encryption 한다. 서티 사이닝을 한다 encrypted 된 RSA 개인키로 공개키를 만든다. pem 키 1. RSA 개인키 생성 openssl genrsa -out private.key 2048 2. RSA 개인키 암호화 아래 두가지 중 택 1 openssl pkcs8 -v1 PBE-SHA1-3DES -topk8 \ -in private.key - [오브젝트; 명령-쿼리 분리](https://platanus.kr/post/2374) - 명령-쿼리 분리 원칙 퍼블릭 인터페이스에 오퍼레이션을 정의할때 참고할 수 있는 지침을 제공. 루틴 Routine : 어떤 절차를 묶어 호출 가능하도록 이름을 부여한 기능 프로시저 Procedure : 정해진 절차에 따라 내부의 상태를 변경하는 루틴의 종류. 부수효과를 발생시킴 함수 Function : 어떤 절차에 따라 필요한 값을 계산해서 반환하는 루틴의 종류. 부수효과가 없다. 명령 Command : 객체의 상태를 - [Ansible 기본 문법](https://platanus.kr/post/2387) - 문법 반복문 Loops — Ansible Documentation - name: Make OpenSSL backup directory file: path: "{{ item }}" state: directory owner: root group: root loop: - /opt/app - /opt/app/log 변수 Using Variables — Ansible Documentation 기본적으로 yml 문법 something_var: "val" 호출시 target: "{{ something_var }}" 작업 생성 / 디렉토리 - name: Creates directory file: path: /src/www - [오브젝트; 디미터 법칙](https://platanus.kr/post/2373) - 인터페이스와 설계 품질 퍼블릭 인터페이스의 품질에 영향을 미치는 원칙과 기법 디미터 법칙 묻지 말고 시켜라 의도를 드러내는 인터페이스 명령-쿼리 분리 디미터 법칙 디미터 법칙 낯선 자에게 말하지 마라.오직 인접한 이웃하고만 말하라.오직 하나의 도트만 사용하라. 클래스 내부의 메서드가 아래 조건을 만족하는 인스턴스에만 메시지를 전송하도록 프로그래밍해야 한다. this 객체 메서드의 매개변수 this의 속성 this의 속성인 컬렉션의 요소 - [2021 1/4 중간점검 part1](https://platanus.kr/post/721) - 오늘 한 것 커리큘럼 중간 점검 의식의 흐름대로 대화 정리 1) 스프링5 초보 개발자를 위한 스프링5 입문 - 가메출판사 스프링5의 코어 부분은 거의 마무리 됐음 (DI, Bean, AOP, Component scan, 자동 주입..) 스프링 DB나 MVC는 설정 지옥임. 특히 DB는 지금 봐도 이해도 안 될 것임. 그래서 스프링 부트로 넘어가서 속도를 내는 것을 추천함 김영한 스프링 입문 - 말랑말랑해서 스프링 부트에 대해 훑어보기 - [2021 1/4 중간점검 part2](https://platanus.kr/post/938) - 2021-02-23 — 1) 안건 스프링부트 더딘 것에 관하여 '스프링 부트 시작하기' 가이드 git flow : 브랜치 관리 전략 2) 여러가지를 다 같이 진행하는 것은 어떤가요? 사실 부트 안본지 일주일 넘었다가 어제 귀찮은거 참고 간신히 함 → 그동안 DB? → DB도 하고 자료구조도 좀 보고, 부트를 안했다고 다른걸 안한건 아니지만 여러가지를 다 할 수 없을까? 느리다기보단 다른것에 몰두해서 그런거 - [2021 1/4 중간점검 part3](https://platanus.kr/post/1091) - 2021-03-09 — 안건 자바 다시 보기 로드맵 짜기 디자인 패턴 책 비교 C 다시보기 로드맵 짜기 자바 로드맵 (20210309) → Do it 자바 프로그래밍 (우테코 할 때 보던거 마저 보기) [ ] Class Object String Wrapper [ ] ⭐️ Generics [ ] Collection → 아는 내용이니 간략하게만 지나가겠음 List ArrayList LinkedList Set HashSet TreeSet Map HashMap TreeMap - [2022 2/4 중간점검](https://platanus.kr/post/1844) - 2022-05-13 — 2022년 2분기 개인 스터디 중간 정리 Java, Spring ✔️ Tomcat - 자바 고양이 Tomcat 이야기 ✔️ JPA - 김영한 Generics Effective Java - 드디어 이 책이 눈에 들어온다. 여기서 파생되는 키워드들 파악 할 것. Concurrency - 뭘 하고 싶어도 이게 전제가 안되니 아무것도 이해 할 수 없음. 기본서 이상의 도움이 필요함. 기차책 Spring Security, Spring - [2022 4/4 중간점검](https://platanus.kr/post/2124) - 2022년 하반기에 한 것 SQL 쿼리 전략 (explain, join, pk) Spring F/W Aspect API 설계 (DTO, ResponseEntity) 대외 활동 - 한빛미디어 서평단 활동 게시판 프로젝트 v2 대외 활동 : 한빛미디어 서평단 2022 2월 : 자바스크립트 무던한 개발자를 위한 모던한 자바스크립트 3월 : MSA 자바 마이크로서비스를 활용한 SRE 4월 : MSA 도메인 주도 개발 시작하기 5월 - [2023 1/4 중간점검](https://platanus.kr/post/2167) - 1Q 활동 정리 2022 4분기 큰 결정 후 일어났던 일들에 대한 기록. 지원현황 경력지원으로 현재 하고 있는 커머스 분야와 자바에 범위를 좁혀서 선별 지원 결과 30전 0승 30패몇 군데 더 있는데 미열람 업체들은 제외함. 면접 및 코테 소감 경력 코딩 테스트 그렇게 어렵지 않다 면접 어렵다 어떤 대기업의 수시 채용은 이력서를 한 달 반을 들고 - [2023 2/4 중간점검](https://platanus.kr/post/2192) - 2Q 활동 정리 뒤늦은 2Q 정리, 너무 바빴고, 사건사고도 많고, 변화도 너무 많았다. 무엇을 했는가 Java Reactor 자바의 스트림 데이터 처리: Flux and FluxSink 리엑터의 테스트: StepVerifier pub/sub 패턴 Backpressure Spring Security 다수의 인증 처리 동시 구현 (OAuth2, formLogin, 커스텀 로그인) Spring Session 세션 공유 스토리지 (세션 직렬화기) 본격 JPA fetch 전략 (연관관계) WebSocket 백엔드 - [2023 3/4 중간점검](https://platanus.kr/post/2200) - 3Q 활동정리 지난 2Q는 횡적인 확장과 JD의 얼라인을 맞추는데 중점을 뒀다면, 3Q는 실제와 종적인 깊이로 다가간다. 무엇을 했는가 Acceptance Test Driven Development 인수 테스트를 배우면서 얻은 것들 테스트의 최종 목적. 코드는 어떻게 작성해야 하는가? JUnit, rich domain, unit test, E2E test, test double. 놀랐던 점 (aka 인지부조화) 이렇게 상세한 테스트를 정말로 나 빼고 모두가 다 - [2023 4/4 중간점검](https://platanus.kr/post/2268) - 4Q 활동정리 지원-면접-탈락 반복커뮤니티 해보기 무엇을 했는가 하반기 지원 (상반기와 바뀐 것) 3Q 회고에서 언급한 프로젝트B가 준비 되어 추가 됨. 경력 기술서 중심의 문제해결 기반 이력서. 내용이 너무 많아서 퇴고 시 줄이는데 대부분의 시간 소요. 10만자 분량의 기술면접 노트 준비. 지원 중간 보고 이것저것 따질때가 아니다 싶어 욕심을 버리고 상반기(30개) 보다 훨씬 많이 지원했고,결과는 내년 - [컴퓨터 시스템 딥 다이브 - 책 소개](https://platanus.kr/post/2339) - 컴퓨터 시스템의 여러 주제를 한번에 관통하는 책! 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 작년에 많은 일들이 있어 고사 했음에도 불구하고 올해 다시 좋은 기회로 한빛미디어의 좋은 책들을 소개할 수 있게 되었다. 양질의 번역서와 국내 좋은 저자들의 IT 지식을 접할 수 있게 도와주시는 한빛미디어에게 감사의 말씀 먼저 드린다. 원제 : Dive Into Systems: - [GPT-4를 활용한 인공지능 앱 개발 - 책소개](https://platanus.kr/post/2385) - 한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다. 원제 : Developing Apps with GPT-4 and ChatGPT 저자 : Caelen, Olivier, Blete, Marie-Alice 출간 : O'Reilly Media, 2023 / 한빛미디어, 2023 ChatGPT 가 이 세상에 등장한지 1년이 됐다. 나도 GPT3.5 첫 출시때부터 사용하기 시작해 지금은 글이나 코드를 작성하는데 도와주는 비서로 많이 활용하고 있다. 이번 책은 - [오브젝트; 메시지와 인터페이스](https://platanus.kr/post/2372) - 객체지향 프로그래밍에서 어플리케이션이 클래스의 집합으로 구성된다는것은 오해다. 클래스라는 구현 도구에 지나치게 집착하면 경직되고 유연하지 못한 설계에 이를 수 있다. 좋은 객체지향 코드를 얻기 위해서 클래스가 아닌 객체를 지향해야 한다. 이는 곧 협력 안에서 객체가 수행하는 책임에 초점을 맞춰야 한다. 책임은 객체가 수신할 수 있는 메시지의 기반이 된다. 협력과 메시지 클라이언트-서버 모델 메시지는 객체 사이의 협력을 - [초심에 접근하는 방법](https://platanus.kr/post/2496) - 세계적으로 유명한 프로듀서 릭 루빈은 역사에 남을 많은 뮤지션들의 음반을 프로듀싱 했다. 내가 아는 뮤지션만 해도 에미넴, Jay-Z, 린킨파크, System of a down, AC/DC, 메탈리카, 레드 핫 칠리 패퍼스 셀수 없을 정도고 특히 그가 프로듀싱한 린킨파크의 A Thousand Suns와 메탈리카의 Death Magnetic은 처음 들었을때 완전히 원초적이고 날 것의 느낌을 간직한 락메탈 밴드의 강렬함에 머리를 두드려 - [오브젝트; 변경과 유연성과 리팩토링](https://platanus.kr/post/2359) - 구현을 통한 검증 메시지를 처리할 책임과 책임을 수행하는데 필요한 변수 지정을 먼저 한다. public class Screening { // 1. '예매하라' 는 메시지에 응답하는 메서드 public Reservation reserver(Customer customer, int audienceCount) { } // 2. 책임을 수행하는데 필요한 인스턴스 변수 private Movie movie; private int sequence; private LocalDateTime whenScreened; } 다른 객체의 구현을 고려할 필요 없이 - [오늘부터 IT를 시작합니다 - 책 소개](https://platanus.kr/post/1955) - "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 저자 : 고코더(이진현) 한빛미디어, 2022 IT계열에 종사하지만 비전공자인 아내가 나에게 개발용어에 대한 질문을 할 때가 종종 있는데 질문을 받으면 아내의 눈높이에서 이해할 수 있도록 쉽게 풀어 설명하려고 잠시 생각을 한다. 물론 설명이 길어지면 아내의 집중력이 떨어지기 때문에 3분 내외로 설명을 마치려고 노력하는 편이다. 책의 부제목을 보고 - [오브젝트; 자율적인 객체](https://platanus.kr/post/2365) - 자율적인 객체를 향해 스스로 자신의 데이터를 책임지는 객체 객체를 설계할 때 "이 객체가 어떤 데이터를 포함해야 하는가?" 라는 질문은 다음과 같은 두개의 개별적인 질문으로 분리해야 한다. 이 객체가 어떤 데이터를 포함해야 하는가? 이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인가? DiscountCondition (할인조건) 클래스에 대한 개선 public class DiscountCondition { private DiscountConditionType type; private int sequence; - [오브젝트; 데이터 중심 설계의 문제](https://platanus.kr/post/2300) - 객체지향 설계의 핵심 협력 : 애플리케이션의 기능을 구현하기 위해 메시지를 주고받는 객체들 사이의 상호작용 책임 : 객체가 다른 객체와 협력하기 위해 수행하는 행동 역할 : 대체 가능한 책임의 집합 객체지향 설계 객체에 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조하는 활동 객체지향의 설계의 핵심은 책임이다. 책임을 할당하는 작업이 응집도와 결합도 같은 설계 품질과 - [오브젝트; 역할, 책임, 협력](https://platanus.kr/post/2296) - 객체지향 패러다임 관점의 핵심 역할 Role 책임 Responsibility 협력 Collaboration 협력 협력 : 객체들이 어플리케이션의 기능을 구현하기 위해 수행하는 상호작용 책임 : 객체가 협력에 참여하기 위해 수행하는 로직 역할 : 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 구성 협력 객체지향 시스템은 자율적인 객체들의 공동체다. 객체는 고립된 존재가 아니라 시스템의 기능이라는 더 큰 목표를 달성하기 - [오브젝트; 객체지향 프로그래밍](https://platanus.kr/post/2284) - 이번 장은 이 책을 읽으면서 이해하게 될 다양한 주제들을 얕은 수준으로 가볍게 살펴보는 것 영화 예매 시스템 책의 예제 소개를 위한 요구사항 할인 조건 순서 조건 : 상영 순번으로 할인 여부 결정 기간 조건 : 영화 사영시작 시간으로 할인 여부 결정 할인 정책 : 할인 할 요금 결정 금액 할인 정책 : 정액 할인 비율 - [오브젝트; 객체, 설계](https://platanus.kr/post/2272) - 이론보다 실무가 먼저다. 설계에 관한 이론은 1970년이 되서야 등장했다. 설계에 대한 이론은 있으나 유지보수에 대한 이론은 없다. 객체지향 프로그램을 설계하고 유지보수하는 데 필요하는 원칙과 기법을 설명하는것이 목적이다. 티켓 판매 어플리케이션 코드 보기 public class Invitation { private LocalDateTime when; } public class Ticket { private Long fee; public Long getFee() { return fee; } } - [OpenSSL을 컴파일을 통해 버전 업그레이드 하기](https://platanus.kr/post/2302) - 목표 패키지 관리자를 통한 바이너리 업데이트가 아니면서 현행 중 가장 stable 버전으로 업데이트 한다. 기존 사용중인 라이브러리를 건드리지 않는다. 시스템에 등록된 OpenSSL을 현행 stable 대체한다. 시스템 준비 기준 Rocky Linux 또는 RHEL 기반 리눅스 인터넷 연결 root 환경 반드시 확인해야 할 것 시스템에 설치된 OpenSSL 버전이 낮으면 높은 버전의 OpenSSL이 필요한 타켓 어플리케이션도 컴파일 해야한다. - [토비 스프링; 오브젝트와 의존관계 (2)](https://platanus.kr/post/2310) - 지난 글에서 DAO 오브젝트 팩토리를 스프링의 Application Context로 변환하는 과정까지 했다. 이 과정에서 @Configuration이라는 어노테이션으로 Application Context가 빈을 만들 수 있게 했다. 1.6 싱글톤 레지스트리와 오브젝트 스코프 그런데 오브젝트 팩토리로 만든 DAO는 여러개 생성이 가능하고 그렇게 되면 동일하지 않게된다.Application Context로 만든 DAO는 동일하다. 1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트 IoC컨테이너인 Application Context는 Singleton Registry다.스프링은 빈을 생성할때 - [포기 하기 직전에](https://platanus.kr/post/2196) - 이 글은 더 화이팅 신장판 1권과 2권에 있는 작가의 에피소드를 정리한 내용이다.작가는 일본에서 더 화이팅 이라는 만화로 1억부 클럽의 반열에 들었다. 더 화이팅은 1989년 연재를 시작해 아직도 연재중이고 단행본 기준으로 130권을 넘게 발매된 만화다. 그러나 그도 더 화이팅을 연재하기까지 계속되는 실패와 커리어에 대한 고뇌가 있었는데, 이 만화를 연재하기 까지 에피소드를 아래 가져와봤다. 이 책을 손에 - [Spring의 테스트 주도 개발 스타일](https://platanus.kr/post/2158) - TDD란 무엇인가? 를 떠나서 스프링 프로젝트에서 TDD를 어떻게 진행하는지에 대한 정리. 여러 스타일 중 한가지 TDD는 기본적으로 테스트 코드를 빌드업 해가면서 개발함. 즉, 이미 한참 완성된 코드를 테스트 하는건 TDD의 방향이 아님. 이런 경우는 있을까? 서비스 로직 서비스 로직을 먼저 POJO로 만든다. 테스트 할 로직을 우선으로 만들면서 서비스 클래스, 엔티티, 영속성 클래스를 만든다. 서비스 로직에서 - [JPA의 연관관계와 즉시로딩 이슈](https://platanus.kr/post/2154) - 연관관계 매핑 테이블과 객체의 연관관계에 대한 패러다임의 차이가 있다. 테이블은 연관관계라고 할 만한 것이 없다 (constraint 제외) 테이블간 연관관계가 필요하면 JOIN을 통해 관계를 갖는 방법 뿐이다. 반면 객체는 참조용 필드가 있으면 그쪽으로 참조가 가능하다. 클래스 내 멤버의 참조를 통해 이뤄진다. 이를 통해 양방향과 단방향 모두 관계를 정립할 수 있다. 연관관계의 주인 테이블은 외래 키 하나로 - [혼자 공부하는 컴퓨터구조 운영체제 - 책 소개](https://platanus.kr/post/2059) - 있어야 할 자리에 모든 내용이 있는 컴퓨터공학 필수 서적 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 제목 : 혼자 공부하는 컴퓨터구조 운영체제 저자 : 강민철 한빛미디어, 2022 국내에서 컴퓨터 구조, 운영체제 과목을 대학 강의가 아닌 책으로 접하기 위해서는 여러 대학 교재를 보거나 흔히 공룡책으로 불리는 Operating System Concepts 를 보는 수 밖에 없었다. - [Database; NoSQL, 모델링](https://platanus.kr/post/506) - 오늘 한 것 CMS에 저장되는 사진의 DB 모델링 백엔드에서 구현 할 때 인터페이스화 하는 것이 좋을것같음 → 백엔드가 어떤 형태(URL, 직접저장, 퍼블릭클라우드) 인지 몰라도 가져오는데 지장이 없게끔 (OCP) 사진, 동영상, 글, 기타 메테데이터를 관리할 방법은? ex) 사진의 형태여도 백엔드가 외부 URL이거나 직접 store된거거나.. 미디어 모델링 UUID 또는 ID 미디어 : 미디어 형태: 사진|동영상|글 ← 왠지 - [자바 객체지향의 원리와 이해 #1](https://platanus.kr/post/484) - 원제 : 스프링 입문을 위한 자바 객체지향의 원리와 이해 저자 김종민 위키북스 2015 1회차 : 키워드 정리 우테코 탈락 후 합격자들로 다른 경쟁자들이 언급하는 객체지향의 설계 5원칙에 대해서 심도 깊은 학습이 필요한 것을 느꼈다. 5원칙 이외에도 타 부트캠프 또는 사전 학습을 통해 역량이 다르다는 것을 말하지 않아도 코드로 엿볼 수 있었다. 다만 가장 공통적인 부분이 — 2021-01-18 - [김상형의 SQL 정복 - 책 소개](https://platanus.kr/post/1933) - '초보 개발자'를 위한 SQL 핸드북 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 저자 : 김상형 한빛미디어, 2021 도서 후기 데이터베이스에 관련된 책은 많다. 대학 강의 서적 처럼 모델링 같은 데이터베이스 이론에 집중된 책 부터 현업에 종사하는 DBA를 위해 DBMS를 매우 딥하게 알려주는 책 까지 데이터베이스에 관한 책은 많이 있다. 그리고 입문자를 위해 DBMS을 - [String, StringBuilder 주요 메서드](https://platanus.kr/post/2048) - Java problem solve를 위한 String과 StringBuilder의 주요 메서드 정리. package main.java; import java.util.Arrays; public class StringBuilderTest { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("By pursuing self-actualization and avoiding self-absorption " + "you may create something bigger than yourself."); StringBuilder asb = new StringBuilder(); asb.append("By"); System.out.println("-------StringBuilder, String 공용---------"); System.out.println(sb.charAt(1)); System.out.println(sb.compareTo(asb)); System.out.println(sb.indexOf("create")); - [GitHub Actions 으로 배포 단계 세분화 하기](https://platanus.kr/post/1588) - 이전에 쓴 GitHub Actions 글이 조회수가 좋아 업데이트 겸 추가 글을 써본다. 사실 저번에 올린 글은 여기저기 많이 돌아다니는 흔한 자바 프로젝트 배포를 위한 Actions 스크립트를 갖다 쓴것이고, 저번 8월 즈음 시간이 생겨 몇가지 더 챙겨봤다. 해당 전체 코드는 GitHub 링크를 첨부한다. 고려해야 할 것은 두가지 정도로 압축된다. 첫번째는 빌드를 어떻게 할 것인가. 두번째는 배포를 - [GitHub Actions 으로 간단한 CD 구성하기](https://platanus.kr/post/1665) - 후속편 안내 본 글이 인기가 좋아 후속편을 작성했다. 아래 간단히 배포하는 것 보다 좀 더 세분화 된 내용을 담았다.글 보러가기 GitHub Actions CI/CD 기본적으로 github action에서 호스트로 push하는 방식이다. GitHub Actions workflow name: remote ssh command for deploy on: push: # main 브랜치에서만 작동합니다. branches: [main] paths-ignore: - 'README.md' - 'docs/**' jobs: build: name: Build - [소프트웨어 아키텍처 The Hard Parts - 책 소개](https://platanus.kr/post/1973) - 분산 아키텍처를 위한 모던 트레이드오프 분석 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Software Architecture : The Hard Parts 저자 : Neal Ford, Mark Richards O'Reilly Media, 2021 / 한빛미디어, 2022 The Hard Parts 이 책은 지난 6월 서평했던 '소프트웨어 아키텍처 101' 의 실전판이다. '소프트웨어 아키텍처 101 서평 보기' 동일한 저자가 - [무던한 개발자를 위한 모던한 자바스크립트 - 책 소개](https://platanus.kr/post/1706) - 우선 좋은 기회를 주신 한빛미디어에 감사의 말씀을 먼저 드린다. 2022년 한 해 동안 의미있는 책들 소개할 수 있는 자격이 주어져서 영광이다. 나는 시스템 엔지니어에서 커리어를 바꿔 개발자가 된 케이스인데 나같은 사람의 시각에서 볼 수 있는 독특한 생각들을 가감없이 풀어내 볼 생각이다. "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 웹 개발자를 위한 빠른 자바스크립트 - [이것이 자바다 (2022 개정판) - 책 소개](https://platanus.kr/post/1962) - 언제나 곁에 두고 바로 찾아보기 좋은 기본서 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 제목 : 이것이 자바다 개정판 저자 : 신용권 , 임경균 한빛미디어, 2022 기본서는 어떻게 다시 찾게 되는가? '이것이 자바다' 는 국내에서 유명한 자바 기본서 중 하나다. 개인적으로 여러 자바 기본서들 중에 가장 좋아하고 개정판이 나왔다는 소식에 서평 신청을 했다. - [클라우드 네이티브 애플리케이션 디자인 패턴 - 책 소개](https://platanus.kr/post/1946) - 마이크로서비스 아키텍처를 구성하는 디자인 패턴 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : Design Patterns for Cloud Native Applications 저자 : Kasun Indrasiri, Sriskandarajah Suhothayan O'Reilly Media, 2021 / 한빛미디어, 2022 이 책에서는 마이크로서비스 아키텍처로 구성되는 서비스를 설계 할 때 인프라, 서비스 배포, 통신, 서비스 조합, 데이터베이스에 대해 어떤 패턴들이 적용될 수 - [MyBatis와 Spring Boot (Annotation)](https://platanus.kr/post/1647) - 2021-06-17 — MariaDB Docker 설치 docker pull mariadb docker run --name mariadb-1 -e MYSQL_ROOT_PASSWORD=PASSWORD -d -p 3306:3306 mariadb docker stop mariadb docker start mariadb DBeaver 설치 DB 생성 create database mybatis_db default character set utf8mb4 default collate utf8mb4_general_ci; create user 'mybatis'@'%' identified by 'thatkxkd123'; grant all on mybatis_db.* to 'mybatis'@'%'; use mybatis_db; create table company ( id - [스프링5; DI의 실제](https://platanus.kr/post/592) - 의존이란? 서비스 객체가 있을때 비즈니스 로직을 처리하는 경우 저장소의 객체를 직접 들여다 볼 수 있다. public class StudentRegisterService { private StudentRepositody studentRepository = new StudentRepository(); //... public void register(Request request) //.. Student student = studentRepository.findByName(studentName); if(student != null){ //.. } } 위와 같은 코드가 있을때 서비스 객체를 생성한다면 자연스럽게 저장소 객체도 생성된다. 이 경우를 두고 - [JDBC의 Prepared Statement](https://platanus.kr/post/1670) - 2021-07-27 — NamedParameterJdbcTemplate NamedParameterJdbcTemplate query() 가장 정확한 사용법 Prepared Statement 일반 JdbcTemplate은 SQL을 실행할때 Prepared Statement 라는게 있는데,쌩 SQL을 사용하는게 아니라 SELECT * FROM user WHERE id = ? 이런식으로 일정 형식문자열로 SQL을 준비하는 것이다.저걸 Prepared Statement 라고 부른다.그러면, 저 쿼리를 DB가 받으면 무슨일을 하냐면. SQL을 파싱하여 대기 상태로 놓는다.→ 만약 기존에 동일한 SQL쿼리가 있었다면 그 쿼리캐시를 - [세션을 사용하기 위한 Filter와 Interceptor](https://platanus.kr/post/1672) - 2021-08-02 — HttpSession 세션 생성을 자동으로 해주는 객체 기본 사용법 @RestController public class SessionInfoController { @GetMapping("/session-info") public String sessionInfo(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return "세션이 없습니다."; } //세션 데이터 출력 session.getAttributeNames().asIterator() .forEachRemaining(name -> log.info("session name={}, value={}", name, session.getAttribute(name))); log.info("sessionId={}", session.getId()); log.info("getMaxInactiveInterval={}", session.getMaxInactiveInterval()); log.info("creationTime={}", new Date(session.getCreationTime())); log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime())); log.info("isNew={}", session.isNew()); - [JdbcTemplate의 SimpleJdbcInsert Bean 등록에 관하여](https://platanus.kr/post/1674) - 2021-08-05 — SimpleJdbcInsert 빈 등록에 대하여 2021-08-05 20:50:00.874 ERROR 14665 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Configuration cannot be altered once the class has been compiled or used] with root cause org.springframework.dao.InvalidDataAccessApiUsageException: Configuration cannot be altered once the class has been - [Spring Argument resolver](https://platanus.kr/post/1678) - 2021-08-12 — RequestMappingHandlerAdapter 어노테이션 기반의 컨트롤러, @RequestMapping을 처리하는 HandlerAdapter. RequestMappingHandlerAdapter 동작 방식 ArgumentResolver 어노테이션 기반의 컨트롤러는 다양한 파라미터를 사용할 수 있다. (HttpServletRequest, Model, @RequestParam, @ModelAttribute, @RequestBody) 이것을 처리할 수 있는 것은 ArgumentResolver기반에서 작동하기 때문이다. 원하는 ArgumentResolver를 만들수도 있다. ReturnValueHandler 컨트롤러의 반환 값을 변환 (ModelAndView, ResponseBody, HttpEntity..) HTTP MessageConverter 각 ArgumentResolver들이 HTTP MessageConverter를 사용해 필요한 객체를 생성한다. 각 - [this가 필요한 상황](https://platanus.kr/post/468) - this this는 클래스 안에서 인스턴스 자기 자신을 바라보는 지시자다.대부분의 상황에서 생략할 수 있지만 몇가지 필요한 상황이 있는데 예시와 함께 정리해보았다. 1. 클래스 변수와 인자의 구분 public void setName(String name) { this.name = name; } 2. 다른 생성자를 호출할때 class Student { public Student(int id) { this(id, “강”); } public Student(int id, String name) { this.id — 2020-12-26 - [스프링5 시작하기 전에](https://platanus.kr/post/455) - JDK 자바를 개발하기 위한 SDK다. JRE; 자바 런타임을 포함하고 있다. 13,14를 깔아도 하위버전을 지원한다. openjdk의 설치 brew tap AdoptOpenJDK/openjdk brew cask install adoptopenjdk8 Maven과 Gradle의 차이 Maven ( 메이븐은 ) brew install maven pom.xml 을 통한 의존 설정 4.0.0 sp5 sp5-chap-2 0.0.1-SNAPSHOT org.springframework spring-context 5.0.2.RELEASE - [자바 객체지향의 원리와 이해 #2](https://platanus.kr/post/490) - 객체지향의 4대 특성에 대해서 알아본다. 이미 알고있는 내용이지만, 책에서는 T메모리 도식을 직접 보여줌으로써 추상화, 다형성, 상속, 캡술화가 각 메모리 영역에 어떤 작용을 하는지 알 수 있었다. 2주차 키워드 Call-By Call By Reference ➡ 주소를 호출, 또는 주소를 해석하여 호출 Call By Address ➡ call by reference와 동일 Call By Value ➡ 값이 호출 된 이후에 — 2021-01-25 - [스프링의 IoC/DI, AOP의 개념](https://platanus.kr/post/513) - 본격적으로 스프링에서 사용되는 코드 패턴과 개념에 대해서 파고 들어간다. IoC/DI IoC; Inversion of Control 제어의 역전 객체를 직접 생성하지 않고 외부에서 구현체를 넣어줌으로써 제어권을 거꾸로 가지고 가는 현상 IoC는 즉, 설계의 패턴이다. 실체에 의존할 것인가 추상화에 의존할 것인가 DI; Dependency Injection 의존성 주입 외부에서 의존성을 받는 행동. 즉, 외부에서 new로 생성된 객체를 받는다. DI는 즉, - [스프링5; 의존 자동 주입 @Autowired](https://platanus.kr/post/629) - 2021-02-02 — Automatic dependency injection 객체에 붙이는 @Autowired 서비스 코드에서 의존주입 받는 객체에 대해 다음과 같이 선언하면 스프링이 bean객체를 직접 찾아서 할당한다 // Service code @Autowired private MemberDao memberDao; bean 설정에서 의존 주입부분을 삭제하더라도 직접 넣는다 public ChangePasswordService changePwdSvc() { ChangePasswordService pwdSvc = new ChangePasswordService(); // pwdSvc.setMemberDao(memberDao()); - [스프링5; Bean 라이프사이클](https://platanus.kr/post/633) - Bean Lifecycle 스프링 컨테이너를 초기화하고 종료할 때는 다음 작업을 수행한다. 컨테이너 초기화 → bean 객체의 생성, 의존 주입, 초기화 컨테이너 종료 → bean 객체의 소멸 초기화와 소멸의 bean 인터페이스 InitializingBean public interface InitializingBean { void afterPropertiesSet() throws Exception; } bean객체가 생성 된 뒤 InitializingBean 클래스의 afterPropertiesSet() 메소드가 호출된다. 초기화 직후 필요한 작업이 있다면 이 클래스를 - [스프링5; AOP의 실제 #2](https://platanus.kr/post/736) - 이전 글 execution 패턴 표현식 execution(public void set*(..)) : 반환형이 void이고, 메소드 이름의 set으로 시작하고 인자가 0개 이상인 메소드를 호출한다. executation(* dto.*.*()) : dto 패키지 탕비에 속한 인자가 없는 모든 메소드를 호출한다. executation(* dto..*.*(..)) : dto 패키지 및 하위 패키지에 있고 인자가 0개 이상인 메소드를 호출한다. execution(Long dto.StudentRepository.getAge(..)) : 반환형이 Long인 StudentRepository 타입의 getAge() 메소드를 - [스프링5; 컴포넌트 스캔](https://platanus.kr/post/631) - 2021-02-03 — Component scan 자동 주입과 함께 사용하는 추가 기능이 component scan이다. 스프링이 직접 클래스를 검색해서 bean으로 등록해주는 기능이다. bean 설정에 등록하지 않아도 원하는 클래스를 bean으로 등록할 수 있어 component scan을 사용하면 bean 설정 코드가 많이 줄어든다. 컴포넌트 스캔의 등록 1) @Component 으로 스캔 대상 지정 서비스 코드에 붙인다 @Component public class MemberDao { //.. } 이렇게 - [스프링5; Prototype 범위](https://platanus.kr/post/636) - 2021-02-03 — Prototype 스프링 컨테이너는 기본적으로 bean객체를 생성 할 떄 싱글톤으로 생성한다. 그러나 여러개의 인스턴스가 필요한 경우 prototype으로 scope를 지정하면 된다. 프로토타입 범위 지정 bean설정에서 scope에 속성으로 지정하면 된다. 아래 코드 참고. @Bean @Scope("prototype") // - [스프링5; AOP의 실제 #1](https://platanus.kr/post/729) - 스프링에서 프록시 패턴을 어떻게 적용시키는지 실제로 스프링을 통해 적용해본다. proxy 패턴은 decorator 객체 로도 활용할 수 있다. 기능 추가와 확장에 초점이 맞춰져있다. 짤막한 프록시의 핵심 프록시의 특징은 핵심 기능은 구현하지 않는다는 점이다. 프록시는 핵심 기능을 구현하지 않는 대신 여러 객체에 공통으로 적용할 수 있는 기능을 구현한다. AOP의 기본 핵심은 공통 기능을 삽입하는 것 이다. AOP의 - [테스트 코드의 작성법 assert](https://platanus.kr/post/830) - 테스트코드 개발된 코드가 예상된 결과값을 내놓는가에 대한 시험 TDD 테스트를 먼저 만들고 구현체를 개발하는 방법 테스트 주도 개발 관례 src 아래 test라는 폴더 아래로 프로젝트와 같은 패키지 구조를 가짐. 테스트하고자 하는 클래스의 끝에 Test라고 붙이는 것이 관례 메소드를 명시하고 @Test 어노테이션을 붙임. junit Assertions사용법 (예시) Assertions.assertEquals(result, member); 결과값 result가 기대값 member를 만족하면 테스트 코드를 통과한다. - [Java; Reflection 개요](https://platanus.kr/post/976) - 리플렉션(Reflection)이란? 자바에서 제공하는 리플렉션(Reflection)은 C, C++과 같은 언어를 비롯한 다른 언어에서는 볼 수 없는 기능입니다. 이미 로딩이 완료된 클래스에서 또 다른 클래스를 동적으로 로딩(Dynamic Loading)하여 생성자(Constructor), 멤버 필드(Member Variables) 그리고 멤버 메서드(Member Method) 등을 사용할 수 있도록 합니다. 그러니까, 컴파일 시간(Compile Time)이 아니라 실행 시간(Run Time)에 동적으로 특정 클래스의 정보를 객체화를 통해 분석 및 추출해낼 - [Java; Generics Type](https://platanus.kr/post/1072) - 2021-03-17 — 제네릭 제네릭이란? 프로그램에서 변수를 선언할 때 모든 변수는 자료형이 있다. 메소드에서 인자를 사용할 때도 자료형을 갖고 있따. 변수나 메소드의 자료형을 필요에 따라 여러 자료형으로 바꿀 수 있다면 프로그램이 훨씬 유연할 것이다. 어떤 갑싱 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍 하는 것을 Generic programming 이라고 한다 Generic 프로그램은 reference 자료형에 대한 - [Collection framework; Collection interface](https://platanus.kr/post/1097) - 2021-03-18 — 컬렉션 프레임워크 프로그램을 개발 할 때 사용하는 자료를 관리하는 방법론이 자료구조다. 자료구조는 프로그램 실행 중 메모리에 자료를 유지, 관리 하기 위해 사용한다. Java에서는 필요한 자료구조를 미리 구현하여 java.util 패키지에 제공하고 있고, 이것을 컬렉션 프레임워크 라고 한다. DAO 컬렉션 예제에 사용할 DAO 코드 memberId와 memberName로 이루어진 getter/setter를 가지는 간단한 DAO다. Collection 인터페이스 Collection 주요 메소드 boolean - [Collection framework; Map interface](https://platanus.kr/post/1293) - 2021-04-22 — Map 인터페이스 Map은 key-value 쌍의 데이터로 표현된다. Map 인터페이스를 구현한 클래스는 내부적으로 해시 알고리즘에 의해 구현되어 있다. Map 주요 메소드 V put(K key, V value) : key에 해당하는 value를 Map에 삽입한다. V get(K key) : key에 해당하는 value를 반환한다. boolean isEmpty() : Map이 비어있는지 반환한다. boolean containsKey(Object key) : Map에 해당 key가 있는지 반환한다. boolean - [Java; Inner Class](https://platanus.kr/post/1352) - 2021-04-23 — 내부 클래스 내부 클래스는 말 그대로 클래스 내부에 선언한 클래스다. 내부 클래스를 선언하는 이유는 외부 클래스와 밀접한 관련이 있기 때문이다. 다른 클래스와 협력할 일이 없을때도 내부 클래스로 선언해서 사용한다. 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스가 있다. 클래스 이름 없이 선언하고 바로 쓸수 있는 익명 클래스도 있다. class A{ // 외부 클래스 class - [Servlet; doGet, doPost](https://platanus.kr/post/1358) - 2021-04-25 — 서블릿 기초 Servlet의 세가지 기본 기능 Servlet이 수행하는 세가지 주요 기능은 다음과 같다. 클라이언트로부터 요청을 받는다. 비즈니스 로직을 처리한다. 처리된 결과를 클라이언트에게 응답으로 내려보낸다. 초기 웹 프로그램 개발에서는 서블릿이 클라이언트로부터 요청을 받아 비즈니스 작업을 처리한 후 그 결과를 클라이언트의 브라우저로 전송하는 방식으로 작업했다. Servlet 요청과 응답 API 요청과 응답에 관련된 API는 모드 javax.servlet.http패키지에 있다. HttpServletRequest - [Java; Stream](https://platanus.kr/post/1375) - 2021-04-27 — 스트림 스트림이란? 배열 요소를 특정 기준에 따라 정렬 하거나 (sort), 요소 중 특정 값은 제외하고 출력하는 기능 (filter). 이런 자료처리에 대한 기능을 구현해놓은 클래스가 stream이다. 스트림을 활용하면 자료를 일관성 있게 처리할 수 있다. 자료에 따라 기능을 새로 구현하는 것이 아니라 자료형에 상관없이 같은 방식으로 메소드를 호출한다. 간단한 스트림 예제 int[] arr = {1,2,3,4,5}; Arrays.stream(arr).forEach(n -> - [Servlet; containter and application structure](https://platanus.kr/post/1286) - 2021-04-21 — 웹 어플리케이션 기존의 정적인 웹 어플리케이션의 기능을 그대로 이용하면서 Servlet, JSP, Java class를 추가하여 사용자에게 동적인 서비스를 제공하는 프로그램을 말한다. 웹 컨테이너에서 실행되는 JSP, Servlet, Java class들을 사용해 정적 웹 프로그래밍 방식의 단점을 보완하여 서비스를 제공하는 서버 프로그램을 웹 어플리케이션이라고 한다. 웹 어플리케이션의 기본 구조 톰캣 = 웹 컨테이너 웹 어플리케이션 구성요소의 기능 ./ : - [Java; Exception](https://platanus.kr/post/1382) - 2021-04-28 — 예외처리 예외 클래스 오류란 무엇인가? 프로그램에서 오류가 발생하는 상황은 Compile error와 runtime error 두가지다 Compile error : 프로그램 코드 작성 실수로 발생하는 오류. 개발 환경에서 대부분의 원인을 알 수 있다. Runtime error : 실행 중인 프로그램이 의도하지 않은 동작을 하거나 프로그램이 중지되는 실행 오류. 프로그램을 잘못 구현해 의도한 바와 다르게 실행됙어 생기는 오류를 버그라고 한다. - [Servlet; DataSource 연동](https://platanus.kr/post/1396) - 2021-04-29 — 서블릿 : 비즈니스 로직 서블릿 비즈니스 처리 작업이란 서블릿이 클라이언트로부터 요청을 받으면 그 요청에 대해 작업을 수행하는 것을 의미 합니다. 대부분의 비즈니스로직 처리는 DB연동 작업이 동반된다. 서블릿의 데이터베이스 연동 DAO와 VO를 사용한 회원정보 연동을 해보자 서블릿으로 회원 정보 테이블의 회원 정보 조회 H2 데이터베이스를 미리 준비한다 create table t_member( id varchar2(10) PRIMARY KEY, pwd varchar2(10), - [Java; I/O Stream](https://platanus.kr/post/1449) - 2021-05-04 — 자바 입출력과 스트림 스트림이란? 자바에서 모든 입출력은 Stream을 통해 이루어진다. 파일 디스크 키보드 모니터 메모리 네트워크 등등 모두 포함. Stream이란 용어는 네트워크에서 유래됐다. 입출력장치가 다양하기 때문에 자바는 입출력 장치와 무관하고 일관성 있게 프로그램을 구현할 수 있도록 일종의 가상 통로인 Stream을 제송한다. Source와 target에 따라 각각 다른 Stream 클래스를 제공한다. 입력 스트림과 출력 스트림 입력 스트림 - [Java; Other I/O stream](https://platanus.kr/post/1465) - 2021-05-18 — 직렬화 직렬화와 역직렬화 클래스의 상태를 저장해 전송하거나 저장할 일이 있다. 그럴때 인스턴스의 어느 순간을 저장하는것을 직렬화라고 한다. (Serialization) 인스턴스의 저장된 상태를 다시 복원하는 것을 역직렬화라고 한다. (Deserialization) 직렬화란 간단하게 인스턴스의 내용을 연속 스트림으로 만드는 것이다. 스트림으로 만들어야 파일에 쓸 수도 있고 네트워크로 전송할 수도 있다. 직렬화를 위한 보조 스트림 ObjectInputStream(InputStream in) ObjectOutputStream(OutputStream out) 직렬화/역직렬화 테스트 - [Java; Optional](https://platanus.kr/post/1581) - 2021-07-21 — 기본적인 사용법 Optional 객체 만들기 Optional 개체 를 만드는 방법에는 여러 가지가 있습니다. 빈 Optional 객체 를 생성하려면 empty() 정적 메서드 를 사용하기만 하면 됩니다 . @Test public void whenCreatesEmptyOptional_thenCorrect() { Optional empty = Optional.empty(); assertFalse(empty.isPresent()); } 값의 비교 isPresent(), isEmpty() isPresent() 메서드를 사용 하여 Optional 객체 내부에 값이 있는지 확인했습니다 . 값은 null 이 - [Java; Generic Methods](https://platanus.kr/post/1839) - 2022-05-03 — 제네릭 메소드 개요 용법 : R method(T t)제네릭 메소드는 매개 타입과 리턴 타입으로 타립 파라미터를 갖는 메소드를 말한다. 제네릭 메소드를 선언하는 방법은 리턴 타입 앞에 기호를 푸가하고 타립 파라미터를 기술한 다음, 리턴 타입과 매개 타입으로 타입 파라미터를 사용하면 된다. // 대강의 형태 public 리턴타입 메소드명(파라미터...) {...} // 실제 사용 public - [IntelliJ 자주 쓰는 단축키 정리](https://platanus.kr/post/836) - 2021-02-13 — 자주 쓰일법한 단축키를 정리해봤다. 생각보다 유용한 context 제시 기능이 많다. Super + K Git commit Super + Shift + K Git push Alt + Return context 제안 보기 (class import, 오타 수정 등등) Super + E 가장 최근에 봤던 파일들 Super + Shift + Return 문장 완성 Super + Alt + V 타입 변형 (Optional 호출 - [객체지향과 클래스](https://platanus.kr/post/1050) - 2020-12-28 — 객체지향의 개념 클래스란 정확히 무엇인가? p.34 간단히 말해서 클래스는 객체에 대한 처사진이다 객체의 인스턴스를 만들 때 객체를 구성하는 기초로 클래스를 사용한다.클래스와 객체를 설명하려고 하는 일은 닭이 먼저냐 계란이 먼저냐 같은 딜레마이다. 객체란 용어를 사용하지 않고 클래스를 설명하기 어렵고 그 반대도 마찬가지이다. 예를 들어, 어느 개인의 자전거는 객체이다. 그러나 누군가 자전거를 만들기 위한 청사진 (즉, 클래스)을 - [캡슐화와 데이터 은닉](https://platanus.kr/post/1052) - 2021-01-13 — 캡슐화와 데이터 은닉 객체 사용에 해당되지 않는 세부 정보는 다른 모든 객체로부터 숨겨야 한다.캡슐화는 객체에 속성과 행위가 같이 포함된다는 사실로 정의된다. 데이터 은닉은 캡슐화의 중요한 일부이다. 예를들어, 어떤 숫자의 제곱을 계산하는 객체가 결과를 얻기 위한 인터페이스를 제공해야 한다고 하자. 그러나 요청하는 객체에서 제곱을 계산하기 위해 사용하는 내부 속성 및 알고리즘을 사용하게 할 필요는 없다. 캡슐화를 - [LinkedList - Single](https://platanus.kr/post/493) - 한방향으로 연결된 연결 리스트의 파이썬 코드 예시 연결 리스트의 필요성 1) 일반적으로 배열을 사용하여 데이털르 순차적으로 저장하고, 나열할 수 있다.2) 배열을 사용하는 경우 메모리 공간이 불필요하게 낭비 될 수 있다. 배열 기반 리스트의 특징 배열로 만들었으므로 특정 위치 원소에 즉시 접근 가능하다. 데이터가 들어갈 공간을 미리 메모리에 할당해야 하는 단점이 있다. 원하는 위치로 삽입이나 삭제가 비효율적이다. -> 주소를 당기고 밀어야하기 때문에. 연결리스트의 — 2021-01-15 - [Database; 모델링, RDB](https://platanus.kr/post/508) - 오늘 한 것 1. 미디어 관련 모델링 (MongoDB) MongoDB에서는 속성의 네이밍을 최대한 줄인다. (성능이슈) // 미디어 schema { mediaId: UUID(), media: { mediaPath : "uri or url string", mediaMetadata: { mediaType:"dedicate,cloud,publish", mediaTitle:"media title string", uploadDate: ObjectId.getTimestamp(), modifiedDate: "timedate", exif:{ //EXIF데이터가 들어가면 좋겠다 }, } } }, // 카테고리 schema { categoryId: UUID(), categoryTitle: "category title - [코딩테스트를 위한 파이썬 정리](https://platanus.kr/post/535) - 알고리즘 스터디를 위해 파이썬에서 코딩테스트를 위해 자주 쓰이는 연산자와 내장함수 관련 내용을 간략하게 정리해봤다. 연산 기존 언어와 파이썬에서 다른 연산자 파이썬에서 나누기는 /와 //가 있다. 전자는 소수점을 표시하고 후자는 정수만을 생성한다. 파이썬의 제곱 연산자는 ** 이다. 그 외 C스타일과 동일. 추가적인 연산관련 내장함수 abs(x) # 절대값 divmod(x, y) # (x//y, x%y) 튜플을 반환한다 round(x, n) - [Database; 모델링 #2](https://platanus.kr/post/528) - 오늘 한 것 1. 미디어 관련 모델링 #2 (MongoDB) // 미디어 schema { mediaId: UUID(), media: { mediaPath : "uri or url string", mediaMetadata: { mediaType:"dedicate,cloud,publish", mediaTitle:"media title string", uploadDate: ObjectId.getTimestamp(), modifiedDate: "timedate", exif:{ //EXIF데이터가 들어가면 좋겠다 }, } } }, 위와 같이 미디어 타입으로 언급된 것은 다음과 같은 고민이 있기 때문이다. 미디어와 글을 같은 - [Graphs](https://platanus.kr/post/872) - 2021-02-18 — Undirected 그래프 Vertex를 연결하는 edge에 순서가 없는 pair로 표현되는 edge들로 이루어져있다. {v1,v2}를 edge라고 표현한다. 예를 들어 v1,v2,v3,v4,v5,v6,v7,v8,v9의 vertex가 있을 때 {v1,v2},{v3,v5},{v4,v7},{v4,v7}의 edge가 있으면 4개의 edge가 있다고 표현한다. 방향이 없기 때문에 v1에서 v2로 가는 edge, v2에서 v1로 가는 edge모두 있다고 본다. 자기 자신에서 자기 자신으로 가는 edge는 없다. V개의 vertext가 있는 방향이 없는 그래프에서 최대한 많은 - [NoSQL의 의의](https://platanus.kr/post/881) - NoSQL의 등장 배경 RDB는 오랜시간 대표적인 DBMS의 자리를 지켜왔다. 그러나 소셜서비스의 규모가 커짐에 따라 비정형 데이터를 이용하고자 하는 빅데이터 개념과 인프라 에코시스템도 클라우드 컴퓨팅의 바람이 불어오면서 기존의 RDB가 가진 단점들이 부각되기 시작했다. RDB를 유지하면서 스케일업 하는것은 한계가 있기 때문이다. 시대적 흐름이 NoSQL의 등장을 이끌었다. RDB의 특징인 ACID 일부를 포기 하고 스키마를 없앴다. 이로인해 비정형 데이터를 - [단방향 암호화 Hash함수](https://platanus.kr/post/541) - Hash 함수 해시함수는 메시지 길이가 길던, 짧던 항상 동일한 길이의 메시지를 만들어내는 함수다. 메시지를 일정한 길이의 블록으로 분할 후 해시 함수에 입력한다. 짧고 일정한 길이의 메시지 다이제스트 (160,256,512bit)생성 대표적인 Hash함수 : MD5, SHA-256, SHA-512 1) Hash 함수의 요구사항 어떤 크기의 데이터 블록이든지 적용 가능해야 한다. 일방향성을 만족해야한다 = 메시지 다이제스트로부터 원래의 메시지를 만들어낼 수 없어야 - [알고리즘; 문자열 해싱 #1](https://platanus.kr/post/588) - 오늘 한 것 알고리즘 교집합 슬라이딩 윈도우 습득한 지식 프로그래머스 Hash; 완주하지 못한 선수 참가자와 완주자의 명단에서 완주하지 못한 참가자를 가져온다. 두 리스트의 교집합을 증명하는 과정에서 완주자와 비교해 참가자를 반환한다 (완주하지 못한 참가자) 소스코드 def solution(participant, completion): participant.sort() completion.sort() r = None for p, c in zip(participant, completion): if p != c: return p if - [알고리즘; 해싱 #2, 스택, 정렬](https://platanus.kr/post/643) - 2월 4일 목요일 알고리즘 스터디에서 진행한 프로그래머스 문제 풀이다. 브레인스토밍과 채점이 끝나고 다른사람의 코드 보기를 보면 파이써닉한 코드가 많은데 그렇게까지 해야 할 필요가 있나 싶다.. 프로그래머스 해시 #3 코드 및 알고리즘 해설 같은 카테고리로 dictionary를 만든다 dictionary key의 길이를 구한다 (총 카테고리의 개수) n개의 카테고리중 1개만 입는 경우를 구한다 → 각 카테고리의 원소 개수를 전부 - [Insertion sort](https://platanus.kr/post/885) - 2021-02-18 — 삽입정렬 sorted된 배열에 원소를 추가할때 sorted가 깨지지 않게 원소의 위치를 찾아서 넣는 알고리즘이 insertion sort다. 각 숫자를 적절한 위치에 삽입하는 정렬 기법이다. 들어갈 위치를 선택하는데 N번, 선택하는 횟수로 N번이지만 선택정렬보다 약간 빠르다. 선택정렬과 똑같이 O(N^2) 의 시간 복잡도를 가진다. 삽입정렬의 작업 순서 가장 앞 인덱스의 원소가 정렬되어있다고 가정했을때 바로 뒷부분의 인덱스부터 올바른 위치로 insertion하는 알고리즘이다. temp변수를 두고 - [Merge sort](https://platanus.kr/post/888) - 2021-02-18 — Divide and conquer 문제를 쪼개서 각각 따로 처리한 다음 결과를 합쳐나가는 방법. Merge 배열의 길이가 1이면 정렬이 끝난 것이다. 아니라면 배열을 반으로 나눠서 왼쪽과 오른쪽을 따로 정렬한다. 둘 다 정렬이 끝나면 merge라는 작업을 통해 배열을 합쳐준다. Merge operation 이미 sorted인 2개의 서브 배열 이 2개의 서브 배열의 merge된, 병합된 하나의 결과를 담을 배열 와 같이 - [Relation Data Model](https://platanus.kr/post/911) - 2021-02-21 — Relation Data model 릴레이션의 예시 Attribute 속성 : 각 데이터를 의미하는 이름 Tuple 투플 : entity instance, record. Domain 도메인 : 속성의 타입을 의미한다. 예를들어 age는 int로 정의할 수 있다. Null Degree 차수 : attribute의 갯수 여기서는 7개다 Cardinality 카디널리티 : tuple(entity instance)의 갯수 Relation의 특징 Tuple의 유일성 : 하나의 relation에는 동일한 tuple이 존재 할 - [Entity-Relationship model](https://platanus.kr/post/909) - 2021-02-21 — Data modeling 데이터 모델링의 과정 개념적 모델링 : 추상화 과정을 통해 중요한 데이터를 추출해 나열한다. 논리적 모델링 : 나열한 데이터의 구조를 결정하고 표시한다. 이 과정을 굳이 분리하지 않고 데이터 모델링으로 이야기한다. 데이터 모델의 구성 데이터 모델은 데이터 모델리의 결과물을 표현하는 도구. 개념적 데이터 모델 : 사람이 이해할 수 있는 모델링을 통해 개념적 구조로 표현 논리적 - [ERD and relation model conversion](https://platanus.kr/post/925) - 2021-02-22 — 데이터베이스 설계는 사용자들의 요구사항을 고려하여 데이터베이스를 생성하는 과정이다. 데이터베이스에 실제로 데이터가 저장되기 시작하면 구조를 변경하기 매우 어렵다. 저장된 데이터와 설계된 구조를 모두 지우고 데이터베이스 scheme을 재작성 해야하는 것은 물론, 어플리케이션에서 데이터베이스에 접근하는 코드 역시 수정이 필요하기 때문이다. 많은 라이브에서 데이터베이스에서 계속 사용중이기 때문에 일관성과 무결성을 지키며 무중단으로 migration 하는 것은 어렵다. RDB모델을 기반으로 두고 데이터베이스를 - [Database normalization](https://platanus.kr/post/941) - 2021-02-24 — Normalization 정규화는 데이터베이스를 설계한 후 설계 결과물을 검증하기 위해 사용하기도 한다. 잘못 설계된 데이터베이스는 이상현상이 발생할 수 있다. 이상 현상 Insertion anomaly 삽입 이상 새 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제 위 릴레이션에서 새로운 tuple을 삽입하려면 이벤트번호과 당첨여부까지 삽입해야 하는 이상현상. 갱신 이상 중복 tuple 중 일부만 변경하여 데이터가 불일치하게 되는 모순의 - [Database transaction](https://platanus.kr/post/954) - Transaction 트랜잭션의 개념 데이터베이스는 다수의 사용자가 동시에 사용하더라도 항상 모순이 없는 정확한 데이터를 유지해야 한다. 장애 상황에서 마찬가지다. DBMS는 데이터가 정확하고 일관된 상태를 유지할 수 있도록 다양한 기능을 제공하는데 그 중에 하나가 트랜잭션이다. 트랜잭션은 한 작업을 수행하는 데 필요한 데이터베이스의 연산들을 모아놓은 것으로 데이터베이스에서 논리적인 작업의 단위가 된다. 장애 발생시 복구하는 작업의 단위도 된다. 트랜젝션의 - [Bit shifting (지수계산)](https://platanus.kr/post/965) - 계산기 2^2 와 같은 바이너리 계산이 필요할 때 256같은 적은 수는 빨리 계산이 되지면 2^23 같은 바이너리는 빠르게 떠오르는 편은 아니다. 부끄럽지만 기존에는 2를 23번 곱하거나 10년도 더 된 공학용 계산기를 쓰거나 구글에서 지수 계산기를 찾아서 해왔다. 그런데 컴퓨터 구조나 디지털 논리회로를 수강하면 알겠지만 비트 쉬프팅으로 지수계산을 쉽게 할 수 있다는걸 알 수 있다. 이걸 계산기에서도 - [DFS/BFS 실제](https://platanus.kr/post/973) - 2021-02-26 — 1) DFS 그래프 탐색 python 코드 구현 def dfs(graph, vertex, visited): # 재귀적으로 처리하는 DFS visited[vertex] = 1 print('{0} '.format(vertex)) # 연결된 다른 노드 방문 for n in graph[vertex]: if visited[n] == 0: dfs(graph, n, visited) if __name__ == '__main__': graph = [ [], [2, 3, 8], [1, 7], [1, 4, 5], [3, 5], [3, - [RESTful API 가이드](https://platanus.kr/post/981) - REST란? REpresentational State Transfer, Roy Fielding REST는 하나의 아키텍처로 볼 수 있다. 좀 더 정확한 표현으로 말하자면, REST 는 Resource Oriented Architecture 이다. API 설계의 중심에 자원(Resource)이 있고 HTTP Method 를 통해 자원을 처리하도록 설계하는 것이다. REST API 디자인 가이드 1) URI는 정보의 자원을 표현해야 한다. → 리소스명은 동사보다는 명사를 사용2) 자원에 대한 행위는 HTTP - [Maven과 gradle의 차이](https://platanus.kr/post/995) - 2021-03-09 — 두 빌드 툴의 사용법은 인터넷에 잘 정리된 글이 많으니 차이점에 대해서 설명해보고자 한다. Maven Apache에서 만든 소프트웨어 프로젝트 관리 및 comprehension 툴이다. POM 개념을 기반으로 프로젝트의 빌드, 보고 및 문서를 중앙 관리할 수 있다. → 프로젝트의 빌드 Lifecycle 기반 프레임워크. mvn 명령어로 관리한다. XML기반의 pom.xml파일로 설정한다. Gradle Maven을 대체할 수 있는 프로젝트 구성 관리 및 - [Strategy pattern](https://platanus.kr/post/1075) - 2021-03-17 — 스트래티지 패턴 전략패턴이라고도 불리는 스트래티지 패턴은 가튼 문제를 해결하는 여러 코드가 클래스별로 캡슐화 되어있고 이들이 필요할 때 교체할 수 있도록 함으로써 동일한 문제를 다른 코드로 해결할 수 이쎅 하는 디자인 패턴이다. 기존 코드 우선 다음 구조의 클래스가 있다고 보자 public abstract class Guitar { private String name; public Guitar(String name) { this.name = name; } - [Singleton pattern](https://platanus.kr/post/1107) - 2021-03-21 — Singleton 싱글톤 패턴은 인스턴스를 하나만 만들어 사용하기 위한 패턴이다. Connection pool, thread pool, device configuration 객체 등과 같은 경우 인스턴스를 여러개 만들게 되면 불필요한 자원을 사용하게 되고, connection pool의 예를 들면 계속 커넥션을 맺고 끊는 작업이 반복되거나 요청이 많아지면 DBMS에 부담이 많이 가게 되는 문제가 발생한다. (마치 php같아진다) 싱글톤 패턴으로 객체를 생성하면 두개의 인스턴스가 존재할 - [Pointer guide; string and array](https://platanus.kr/post/1119) - 2021-03-27 — 문자열과 배열 그리고 포인터의 관계 포인터 변수 포인터를 사용하기 위해서 포인터 변수를 먼저 선언 후 주소를 할당한다. int a[10]; int *pa; pa = &a[0]; // 이것은 아래와 같다 pa = a; &a[0]가 a와 동치인 이유는 배열의 첫번째 요소의 시작주소와 배열의 주소가 같기 때문이다. 포인터 변수와 함수 매개변수의 원본 조작이 필요할때는 포인터 변수로 선언한다. void swap - [Pointer guide; method and memory](https://platanus.kr/post/1123) - 2021-03-29 — 함수 내에서 포인터 변수 사용 요령 1. 선언부 다음의 선언이 있다고 하자 char *strcpy(char *dest, char *src) char *strcpy 이 선언은 char형의 포인터, 즉 문자열로 반환하고 포인터 변수 dest와 src를 매개변수로 받는 포인터 함수다. char *dest의 정확한 표기법은 사실 char* dest다. 그래서 함수 내에서 다음 주소를 참조하기 위해 조작시 *dest++ 식으로 조작하면 안되고 dest++가 맞다. - [Pointer guide; iterator and manipulate](https://platanus.kr/post/1129) - 2021-03-30 — 포인터 : 문자열 순회와 조작에 관하여 int main(void) { // char *src = "asdfG"; char src[55] = {'a','s','d','f','G'}; printf("%s\n", src); printf("%s\n", strupcase(src)); return (0); } char src[55] : 문자열 조작을 위해서 상수가 아닌 스택 또는 힙 영역으로 할당해야한다. #include char *strupcase(char *str) { char *tmp_str; tmp_str = str; while(*tmp_str != '포인터 : 문자열 순회와 조작에 관하여 int main(void) { // char *src = "asdfG"; char src[55] = {'a','s','d','f','G'}; printf("%s\n", src); printf("%s\n", strupcase(src)); return (0); } char src[55] : 문자열 조작을 위해서 상수가 아닌 스택 또는 힙 영역으로 할당해야한다. #include char *strupcase(char *str) { char *tmp_str; tmp_str = str; while(*tmp_str != '#post_content') { if (*tmp_str') { if (*tmp_str - [string.h functions](https://platanus.kr/post/1133) - 2021-04-02 — 문자열과 관련된 함수 C의 string과 관련된 함수들 몇 가지를 정리 해봤다. 위는 string.h 함수의 원형이고 아래는 간단히 구현해본 코드다. strcat char *strcat(char * restrict s1, char * restrict s2) s2가 가리키는 문자열의 복사본을 (NULL문자까지 포함하여) s1이 가리키는 위치에 붙인다. s2 문자열의 첫번째 문자가 s1문자열의 NULL문자를 덮어 쓴다. s1을 리턴한다 char *ft_strcat(char *dest, char *src) { char *tmp_dest; - [Pointer guide; multiple pointer](https://platanus.kr/post/1229) - 2021-04-08 — 포인터 가이드 : 다중 포인터 다루기 변수 포인터의 가장 적절한 예는 배열과 문자열이다. 배열의 가장 앞 원소(element)의 주소는 배열의 시작 주소와 동치다. char형의 배열은 곧 문자열이다. 맨 앞 문자의 주소는 문자열의 시작 주소와 동치다. 이러한 배열 자체를 원소로 삼아 또 다른 배열을 만들 수 있다. 어렵게 생각할 것 없이 아래 도식을 보자. 각각 요소 3개를 가진 - [Pointer guide; struct](https://platanus.kr/post/1239) - 2021-04-12 — 구조체 포인터 다뤄보기 아래 코드가 있다 typedef struct string_struct { int size; char *str; char *copy; } string_s; struct string_struct *ft_table_to_struct(int ac, char **av) { int i; struct string_struct *data_arr; if (!(data_arr = malloc((ac + 1) * sizeof(struct string_struct)))) return (0); i = 0; while (i < ac) { data_arr[i].size = ft_strlen(av[i]); data_arr[i].str = av[i]; - [State pattern](https://platanus.kr/post/1243) - 2021-04-19 — State 패턴 실세계의 많은개체는 자신이 처한 상태에 따라 일을 다르게 수행한다. 비가 오거나 눈이 오거나 사람이 많이 붐비는 장소에 있거나 따라 걷는 방식과 말하는 방식이 달리지는 것과 마찬가지인 이치다. 이를 표현하는 가장 직접적이고 직관적인 방법은 이를 수행할 때의 상태에 따라 상태 하나하나를 검사해 일을 다르게 수행하게끔 하는 것이다. 이는 분명히 복잡한 조건식이 있는 코드를 산출할 - [Command pattern](https://platanus.kr/post/1276) - 2021-04-21 — Command 패턴 Command패턴은 이벤트가 발생했을 때 실행될 기능이 다양하면서도 변경이 필요한 경우에 이벤트를 발생시키는 클래스를 변경하지 않고도 재사용을 가능하게 할때 유용하다. 실행될 기능을 캡슐화함으로써 기능의 실행을 요구하는 Invoker 클래스와 실제 기능을 실행하는 Receiver클래스 사이의 의존성을 제거한다. 따라서 실행될 기능의 변경에도 Invoker 클래스를 수정없이 그대로 사용할 수 있도록 해준다. 만능버튼 만들기 램프를 켜는 버튼을 만들어보자 public - [Observer pattern](https://platanus.kr/post/1283) - 2021-04-21 — Observer 패턴 Oberver패턴은 데이터의 변경이 발생했을 경우 상대 클래스나 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때 유용하다. 예를 들어 새로운 파일이 추가되거나 기존 파일이 삭제되었을 때 탐색기는 이를 즉시 표시할 필요가 있다. 다른 예로는 차량의 연료가 소진될 떄 까지 주행 가능 거리를 출력하는 클래스, 연료량이 부족하면 메시지를 보내는 클래스 등이 있다. 성적 출력 툴 - [Template method pattern](https://platanus.kr/post/1344) - 2021-04-23 — Template method 패턴 템플릿 메소드 패턴은 전체적으로 동일하면서 부분적으로는 다른 구문으로 구성된 메소드의 코드 중복을 최소화 할 때 유용하다. 다른관점에서 보면 동일한 기능을 상위 클래스에서 정의하면서 확장과 변화가 필요한 부분만 서브 클래스에서 구현할 수 있도록 한다 여러 회사의 모터 지원하기 엘리베이터 제어 시스템에서 모터를 구동시키는 기능을 생각해보자. 예를 들어 A모터를 이용하는 제어잇스템이라면 AMotor 클래스에 move()메소드를 - [Factory method pattern](https://platanus.kr/post/1361) - 2021-04-25 — Factory method 패턴 팩토리 메소드 패턴은 객체의 새성 코드를 별도의 클래스 또는 메소드로 분리함으로써 객체 생성의 변화에 대비하는데 유용하다. 프로그램이 제공하는 기능은 상황에 따라 변경될 수 있다. 그리고 특정 기능의 구현은 개별 클래스를 통해 제공되는 것이 바람직한 설계다. 그러므로 기능의 변경이나 상황에 따른 기능의 선택은 바로 해당 객체를 생성하는 코드의 변경을 초래한다. 게다가 상황에 따라 - [Abstract Factory pattern](https://platanus.kr/post/1370) - 2021-04-27 — Abstract factory 패턴 추상 팩토리 패턴은 관련성 있는 여러 종류의 객체를 일관된 방식으로 생성하는 경우에 유용하다. 계속되는 엘리베이터 예제에서 벤더에 따른 코드를 작성하면 벤더가 바뀌었을때 모든 부품의 코드가 벤더를 이동해야한다. 이런 경우에 부품별로 Factory를 정의하는 대신 관련 객체들을 일관성 있게 생성 할 수 있도록 Factory클래스를 정의하는 것이 효과적이다. 예를들어 Motor클래스를 위한 MotorFactory나 Door클래스를 위한 DoorFactory - [Composite pattern](https://platanus.kr/post/1389) - 2021-04-28 — Composite 패턴 컴포짓 패턴은 part-whole의 관계를 갖는 객체들을 정의할때 유용하다. 여러 객체가 한 클래스 전체 객체의 일부분으로 정의될때 사용한다. 부분 객체의 추가나 삭제가 있어도 전체 클래스의 코드를 변경하지 않으면 컴포짓 패턴은 유용하다. 그리고 클라이언트는 whole과 part를 구분하지 않고 동일한 인터페이스를 가질 수 있다. 컴퓨터에 추가 장치 지원하기 컴퓨터를 모델링해보자. 컴퓨터에는 Keyboard, Monitor, RAM, SSD, CPU등이 - [Introduce Operating System](https://platanus.kr/post/1348) - 2021-04-21 — 커리큘럼이 짬뽕식이긴 한데 하다보니 운영체제를 공부하게 됐다. 프로세스 생명주기나 메모리 관리에 대한 내용을 보다보니 지나칠 수가 없었다. 처음엔 Operating System Concepts 책을 보려고 했으나 시간적인 문제도 있고 개론적으로 내용을 알고 있기 때문에 Operating System Concepts Essentials로 진행하기로 했다. 너무 많은 내용을 담지 않겠다. 운영체제가 할 일 컴퓨터 시스템은 대게 하드웨어, 운영체제, 응용프로그램, 사용자 네가지 구성요소로 - [OS Structure](https://platanus.kr/post/1350) - 2021-04-23 — 운영체제 구조 운영체제는 프로그래밍이 실행되는 환경을 제공해 준다. 운영체제를 살펴보는 몇가지 관점이 있다. 첫번째는 운영체제가 제공하는 서비스에 초점을 맞추는 것 두번째는 운영체제가 사용자 및 프로그래머에게 제공하는 인터페이스에 초점을 맞추는 것 세번째는 시스템의 구성요소와 그들의 상호연겨에 초점을 맞추는 것 운영체제 서비스 User Interface : 거의 모든 운영체제는 UI를 제공한다. CLI와 GUI가 있다. Program execution : 시스템은 - [Process](https://platanus.kr/post/1404) - 2021-04-29 — 프로세스 초기의 컴퓨터 시스템은 한번의 하나의 프로그램만 실행하도록 허용했다. 오늘날 컴퓨터는 메모리에 다수의 프로그램들이 적재되어 병행 실행되는 것을 허용한다. 제어와 구획화의 필요성에 따라 프로세스의 개념이 생겼다. 프로세스란 실행중인 프로그램이다. 프로세스 개념 CPU활동을 지칭하는 이름 일괄처리 시스템 : Job 시분할 시스템 : 사용자 프로그램, Task 이러한 명칭들이 있지만 모두 프로세스라고 부른다. 프로세스 프로세스는 텍스트 섹션으로 알려진 - [Thread](https://platanus.kr/post/1455) - 2021-05-10 — 스레드 스레드는 CPU이용의 기본 단위다. 스레드는 다음으로 구성된다 스레드ID 프로그램 카운터 레지스터 집합 스택 스레드는 같은 프로세스에 속한 다른 스레드와 코드, 데이터 섹션 그리고 열린 파일이나 시그널과 같은 운영체제 자원들을 공유한다. Motivation 어플리케이션은 멀티 코어를 사용하여 다수의 CPU집중 작업을 병렬로 처리할 수 있다 프로세스와 스레드가 하나인 시스템에서는 여러개의 동시 요청에 하나씩 처리할 수 밖에 없다. - [Process synchronization](https://platanus.kr/post/1471) - 2021-05-28 — 프로세스 동기화 협동 프로세스는 시스탬 내에서 실행중인 다른 프로세스의 실행에 영향을 주거나 영향을 받는 프로세스다. 협동 프로세스에서 데이터 공유는 동시접근에 의한 데이터의 비 일관성을 낳을 수 있다. 협동 프로세스의 질서있는 실행을 보장하며, 이를 통해 데이터의 일관성을 유지하는 기법을 알아보자. 배경 프로세스는 동시 또는 병렬로 실행될 수 있다. CPU 스케줄러가 프로세스 사이에서 빠르게 오가며 각 프로세스를 - [CPU Scheduling](https://platanus.kr/post/1474) - 2021-05-30 — CPU 스케줄링 스레드를 지원하는 운영체제에서는 실질적으로 운영체제는 프로세스가 아니라 커널 수준 스레드를 스케줄 한다. 프로세스 스케줄링과 스레드 스키줄링은 상호교환적으로 사용된다. 일반적인 스케줄링 개념을 논의하는 경우 프로세스 스케줄링을 사용하고 스레드에 국한된 개념을 가리키는 경우 스레드 스케줄링이라는 용어를 사용한다. 기본 개념 단일 프로세서 시스템에서는 한 순간에 오직 하나의 프로세스만이 실행할 수 있다. 다중 프로그래밍의 목적은 CPU 이용률을 - [Memory](https://platanus.kr/post/1479) - 2021-06-01 — 메모리 관리 프로세스에게 메모리를 할당하는 방법 컴퓨터 시스템에서 페이징의 동작 방법 배경 메모리는 각각 주소가 할당된 이련의 바이트들로 구성된다. CPU는 프로그램 카운터가 지시하는 대로 메모리로부터 다음 명령어를 가져온다. 명령어는 필요한 경우 추가적인 데이터를 더 가지고 올수도 있고 내보낼 수도 있다. 기본 하드웨어 메인 메모리와 프로세서 자체에 내장되어 있는 레지스터들은 CPU가 직접 접근할 수 있는 유일한 - [Virtual Memory](https://platanus.kr/post/1486) - 2021-06-04 — 가상 메모리 가상 메모리라는 것은 프로세스 전체가 메모리 내에 올라오지 않더라도 실행이 가능하도록 하는 기법이다. 이 기법의 주요 장점중 하나는 사용자 프로그램이 물리 메모리 보다 커져도 된다는 점이다. 배경 많은 경우에 프로그램 전체가 한꺼번에 메모리에 늘 올라와있어야 하는것은 아니다 아래의 예시가 있다. 프로그램에는 잘 발생하지 않는 오류 상황을 처리하는 코드가 종종 존재한다. 이러한 오류들은 거의 - [git flow의 실제 사용](https://platanus.kr/post/1668) - 2021-06-24 — git을 잘 쓰기 위한 브랜치 사용법 main이나 develop등 공용 브랜치에 커밋을 하지 않는다 → feature 브랜치로 따로 따서 작업한다. git checkout -b "feature/NUM" 공용 브랜치를 자주자주 pull 받아 브랜치를 최신으로 유지한다 (예를들어 develop) 공용 브랜치는 upstream으로 지정한다 git remote add upstream [URL] git pull upstream [공용브랜치] git push origin [공용브랜치] git의 커밋 흐름은 파일 단위가 - [VueJS를 시작 하면서 필요한 것들](https://platanus.kr/post/325) - Vue.js를 이용해 간단한 클라이언트 프론트엔드를 제작하면서 필요했던 것들을 정리해봤다. 서버단의 경우 호출/반환은 flask, 내부 구현은 python으로 미리 제작을 완료하였다. 클라이언트를 평소 익숙했던 php로 간단한 웹페이지로 제작하고자 했으나 차후 데스크탑 어플리케이션 또는 모바일 앱으로 래핑 할 것을 고려해 모두 한 코드에 통합할 수 있는 프레임워크를 찾기 시작했다. 무엇보다 내부 구현이 모두 완료되었기 때문에 빠르게 제작할 수 - [나만의 작은 스토리지를 위한 여정](https://platanus.kr/post/851) - 개요 자작 스토리지를 만들어 2016년부터 지금까지 사고 없이 잘 사용하고 있다. 2010년 초반에 집집마다 NAS를 들여야 한다는 광풍이 한차례 지나가고 뒤늦게 스토리지를 장만한 것이다. 땡놀로땡이나 땡냅 같은 벤더들이 개인 및 소규모 업장을 위한 NAS 박스를 많이 만들고 있다. 그러나 RAID나 데이터 저장의 이해 부족으로 적지 않은 고통을 유저들이 떠안고 있다고 생각한다. 용량을 위해 RAID0 (스프라이팅) - [Docker 시작하기](https://platanus.kr/post/997) - 2021-03-11 — Windows 10과 맥에서 docker를 설치하고 WSL과 통합하여 기본적인 컨테이너를 올려보는 기회. Windows10 + WSL2 + Ubuntu 현 시점에서 WSL2+Ubuntu는 기본 사양이므로 넘어가도록 하겠다. 필요하면 이 링크 참고. 바쁜 사람들을 위한 짧은 코드 (powershell에서 실행해야된다) dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart WSL 설치 후 MS스토어에서 Ubuntu를 받으면 된다. 대부분 Ubuntu를 - [metadata를 기반으로 한 LVM volume 복구](https://platanus.kr/post/1601) - 2021-08-16 — 증상 아직 복구중이긴 하지만 내역으로 한번 써본다.만약 수행한다면 dd등을 통해 데이터를 백업 후 한번 읽어보고 본인의 상황에 얼마나 도움이 될지 읽어보고 진행하길 바란다. LVM에 SSD캐시를 붙여서 쓰고있었다. writethrough 모드로 쓴다고 안심하고 있었으나 SSD가 돌연사 함으로 인해 LVM 볼륨에도 접근할 수 없는 상태가 됐다. (IO error 상태) 이 진단을 내리기 전에는 단순히 파일시스템이 깨진것으로 판단하고 언마운트 - [SSL 인증서와 Wordpress 설치](https://platanus.kr/post/1811) - 2022-04-18 — 최근 브라우저들이 Mixed contents 사용을 강제로 막으면서 Wordpress에 SSL 인증서를 적용하는 것이 매우 복잡해졌다. Wordpress를 새로 설치할 일이 있었는데 443 만으로 진행했다가 매우 큰 낭패를 보고 며칠간 삽질 했다.. 간단하게 요오오즘 트랜드에 맞는 설정을 적용하기 위한 작업순서도를 정리해본다. 1. 443(SSL)만 열어놓고 설치를 시도하면 발생하는 이슈 설치 화면 부터 Mixed contents 경고가 발생함 그 화면에서 설치해도 - [시작](https://platanus.kr/post/13) - 처음 쓰는 글 평소에 생각하고 고민하는 것들에 대한 풀어쓰기를 합니다.대한민국 서울 30대. - [깡통 찬 아저씨의 생에 첫 CS 개발 감상](https://platanus.kr/post/346) - 전편에 이어서 작성한다. 내부 처리와 클라이언트 대응을 위한 API 서버와 일반 대중들을 대상으로 하는 웹 어플리케이션을 개발했다. 당연히 기능 추가나 보완해야 할 부분이 많지만, 깡통 찬 아저씨가 백지에서 두 달 만에 굴러가는 수준의 앱을 만들었다는 이야기를 정리해본다. 개요는 웹사이트를 핸들링하여 데이터를 가져와 구조를 만들고 내부에서 여러가지 라이브러리로 처리한다는 내용이다. 클라이언트는 서버가 주는 가공된 데이터를 시각화 - [42 서울 La Piscine 후기](https://platanus.kr/post/1257) - 2021-04-23 — 42서울? 42서울은 프랑스의 에꼴42 교육 시스템을 그대로 가지고와 과기부에서 운영하고 있는 프로그래머 인재양성 교육과정이다. 커리큘럼부터 내부 인트라넷까지 전부 프랑스의 시스템을 그대로 사용하고 있다. 42만의 특이한 점이라면 강사나 강의가 없고 피어리뷰 위주의 커리큘럼 진행이 특징이다. 과제가 주어지고 동료학습을 통해 문제를 해결해나가는 방식이다. 이 점이 가장 마음에 들었다. 한국에서는 매달 100만원의 지원금을 준다. 특이하게도 예비과정에서도 지원금을 지급한다. - [SOLID; 객체지향 설계의 5원칙](https://platanus.kr/post/511) - 이 부분은 1회차 지만 신경써서 머릿속에 넣어본다. 실제로 설계하거나 구현 할 때 적절한 모델링(추상화)와 인터페이스의 분리에 신경쓸 필요가 있겠다. 그러나 SRP-ISP와 OCP-DIP 관계의 뉘앙스 차이는 아직 잘 모르겠다. 객체지향 설계의 5원칙 SRP; 단일 책임 원칙 OCP; 개방 폐쇄 원칙 LSP; 리스코프 치환 원칙 ISP; 인터페이스 분리 원칙 DIP; 의존 역전 원칙 아주 간단한 요약 1. - [파이썬의 정렬과 힙 #1](https://platanus.kr/post/741) - 2021-02-08 — python의 sort 커스텀 정렬의 기준이 되는 가중치를 key 필드로 임의 지정할 수 있다. # 1. 튜플의 합을 가중치로 두는 정렬 def take_sum(elem): return elem[0] + elem[1] random = [(2, 2), (3, 4), (4, 1), (1, 3)] sorted_list = sorted(random, key=take_sum) print('Sorted list:', sorted_list) 원소가 이터러블일때 모두 사용가능하다. # 2. 문자열의 join를 가중치로 두는 정렬 def - [자바 마이크로서비스를 활용한 SRE - 책 소개](https://platanus.kr/post/1763) - 2022-03-31 — MSA로 구축된 어플리케이션 관리를 단계적으로 안내하는 실전 가이드 "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 원제 : SRE with Java Microservices 저자 : Jonathan Schneider O'Reilly Media, 2020 / 한빛미디어, 2022 한국에서 MSA는 채용 시장에서 가장 핫한 주제다. MSA는 대용량 서비스를 안정적으로 운영하기 위해 느슨한 결합도, 무중단 배포, 기민한 릴리즈 대응, 탈중앙화에 부합해 - [도메인 주도 개발 시작하기 - 책 소개](https://platanus.kr/post/1832) - 2022-04-24 — "한빛미디어 활동을 위해서 책을 제공받아 작성된 서평입니다." 저자 : 최범균 한빛미디어, 2022 / 지앤선, 2016 범균님의 DDD 입문서가 재발간 되었다. 개인적으로는 스프링 입문을 이분 책✳︎으로 하게 되서 반가운 마음에 읽게 되었다. 에릭 에반스의 DDD를 바로 보는 것이 가장 베스트지만 서점에서 몇 번을 시도 했다가 나에게 문턱이 너무 높아 매번 후순위로 밀려났다. (그 외에 - [REST의 의미와 연결된 지식들](https://platanus.kr/post/988) - REST REpresentational State Transfer, Roy Fielding REpresentational State Transfer → 표현 상태 전송 월드 와이드 웹(World Wide Web a.k.a WWW)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식으로 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반에 대한 패턴이다. REST가 디자인 패턴이다, 아키텍처다 많은 이야기가 존재하는데, 하나의 아키텍처로 볼 수 있다. 좀 더 정확한 표현으로 - [APFS 남은용량 늘리기](https://platanus.kr/post/279) - 부트캠프 삭제 이후 빈 공간을 맥용 파티션으로 늘릴려고 하니 사진상의 895GB에서 더이상 늘어나지 않는다. 숫자를 따로 입력해도 늘어나지 않는다.diskutil 명령으로 해결할 수 있나 확인해보니 뾰족히 그런것도 아닌것 같다. 오히려 명령어가 더 부실한 경우인것 같다. 저 '여유 공간'에 컨테이너를 만들었다 볼륨을 만들었다 방법을 해봐도 소용이 없던 차에 '여유 공간' 이라는 이름을 찍어보니 아래에 '-'버튼이 활성화가 된다. ## 카테고리 - [미분류](https://platanus.kr/post/category/uncategorized) - [Blog](https://platanus.kr/post/category/blog) - 개발에 관한 이런저런 이야기들. - [Engineering](https://platanus.kr/post/category/build) - [TIL](https://platanus.kr/post/category/til) - [Java programming](https://platanus.kr/post/category/java/java-programming-language) - [Spring Framework](https://platanus.kr/post/category/java/spring-framework) - [Database](https://platanus.kr/post/category/cs/database) - [Fundamental](https://platanus.kr/post/category/cs) - [Data structure](https://platanus.kr/post/category/cs/data-structure) - [Algorithm](https://platanus.kr/post/category/cs/algorithm) - [Operating System](https://platanus.kr/post/category/cs/operating-system) - [OOP](https://platanus.kr/post/category/cs/oop) - [C](https://platanus.kr/post/category/cs/c-programming-language) - [Design pattern](https://platanus.kr/post/category/cs/design-pattern) - [Problem solving](https://platanus.kr/post/category/cs/solve) - [Mapper](https://platanus.kr/post/category/java/mapper) - [JPA](https://platanus.kr/post/category/java/jpa) - [Linux](https://platanus.kr/post/category/build/linux) - [Book Review](https://platanus.kr/post/category/blog/book) - IT 서적을 소개하는 자리. - [Web application](https://platanus.kr/post/category/build/service) - [Think](https://platanus.kr/post/category/blog/think) - 나의 생각과 개발에 관한 이런저런 이야기 - [Co-work](https://platanus.kr/post/category/build/work) - [Cloud Infrastructure](https://platanus.kr/post/category/build/cloud-infra) - [Network](https://platanus.kr/post/category/cs/network) - [Java Eco](https://platanus.kr/post/category/java) - [AI](https://platanus.kr/post/category/build/ai) ## 태그 - [lvm](https://platanus.kr/post/tag/lvm) - [cache](https://platanus.kr/post/tag/cache) - [lvmcache](https://platanus.kr/post/tag/lvmcache) - [lvm캐시](https://platanus.kr/post/tag/lvm캐시) - [linux](https://platanus.kr/post/tag/linux) - [cloud](https://platanus.kr/post/tag/cloud) - [spring](https://platanus.kr/post/tag/spring) - [jdk](https://platanus.kr/post/tag/jdk) - [maven](https://platanus.kr/post/tag/maven) - [gradle](https://platanus.kr/post/tag/gradle) - [idea](https://platanus.kr/post/tag/idea) - [intellij](https://platanus.kr/post/tag/intellij) - [pointer](https://platanus.kr/post/tag/pointer) - [function pointer](https://platanus.kr/post/tag/function-pointer) - [Java](https://platanus.kr/post/tag/java) - [oop](https://platanus.kr/post/tag/oop) - [language](https://platanus.kr/post/tag/language) - [cdb](https://platanus.kr/post/tag/cdb) - [soa](https://platanus.kr/post/tag/soa) - [T Memory](https://platanus.kr/post/tag/t-memory) - [class](https://platanus.kr/post/tag/class) - [Abstract](https://platanus.kr/post/tag/abstract) - [inheritance](https://platanus.kr/post/tag/inheritance) - [extend](https://platanus.kr/post/tag/extend) - [interface](https://platanus.kr/post/tag/interface) - [polymorphism](https://platanus.kr/post/tag/polymorphism) - [encapsulation](https://platanus.kr/post/tag/encapsulation) - [call-by](https://platanus.kr/post/tag/call-by) - [constructure](https://platanus.kr/post/tag/constructure) - [final](https://platanus.kr/post/tag/final) - [instanceof](https://platanus.kr/post/tag/instanceof) - [overloading](https://platanus.kr/post/tag/overloading) - [overriding](https://platanus.kr/post/tag/overriding) - [linkedlist](https://platanus.kr/post/tag/linkedlist) - [singlelinkedlist](https://platanus.kr/post/tag/singlelinkedlist) - [data structure](https://platanus.kr/post/tag/data-structure) - [python](https://platanus.kr/post/tag/python) - [this keyword](https://platanus.kr/post/tag/this-keyword) - [mongodb](https://platanus.kr/post/tag/mongodb) - [modeling](https://platanus.kr/post/tag/modeling) - [scheme](https://platanus.kr/post/tag/scheme) - [rdb](https://platanus.kr/post/tag/rdb) - [eav](https://platanus.kr/post/tag/eav) - [entity](https://platanus.kr/post/tag/entity) - [uuid](https://platanus.kr/post/tag/uuid) - [srp](https://platanus.kr/post/tag/srp) - [ocp](https://platanus.kr/post/tag/ocp) - [lsp](https://platanus.kr/post/tag/lsp) - [isp](https://platanus.kr/post/tag/isp) - [dip](https://platanus.kr/post/tag/dip) - [ioc/di](https://platanus.kr/post/tag/ioc-di) - [aop](https://platanus.kr/post/tag/aop) - [aspect](https://platanus.kr/post/tag/aspect) - [design pattern](https://platanus.kr/post/tag/design-pattern) - [proxy](https://platanus.kr/post/tag/proxy) - [database](https://platanus.kr/post/tag/database) - [algorithm](https://platanus.kr/post/tag/algorithm) - [coding test](https://platanus.kr/post/tag/coding-test) - [coding interview](https://platanus.kr/post/tag/coding-interview) - [combination](https://platanus.kr/post/tag/combination) - [permutation](https://platanus.kr/post/tag/permutation) - [window sliding](https://platanus.kr/post/tag/window-sliding) - [hashing](https://platanus.kr/post/tag/hashing) - [di](https://platanus.kr/post/tag/di) - [dependency injection](https://platanus.kr/post/tag/dependency-injection) - [autowired](https://platanus.kr/post/tag/autowired) - [setter](https://platanus.kr/post/tag/setter) - [hash](https://platanus.kr/post/tag/hash) - [encrypt](https://platanus.kr/post/tag/encrypt) - [crypt](https://platanus.kr/post/tag/crypt) - [sha](https://platanus.kr/post/tag/sha) - [md5](https://platanus.kr/post/tag/md5) - [sha-256](https://platanus.kr/post/tag/sha-256) - [nullable](https://platanus.kr/post/tag/nullable) - [optional](https://platanus.kr/post/tag/optional) - [qualifier](https://platanus.kr/post/tag/qualifier) - [component scan](https://platanus.kr/post/tag/component-scan) - [component](https://platanus.kr/post/tag/component) - [bean](https://platanus.kr/post/tag/bean) - [InitializingBean](https://platanus.kr/post/tag/initializingbean) - [DisposableBean](https://platanus.kr/post/tag/disposablebean) - [bean lifecycle](https://platanus.kr/post/tag/bean-lifecycle) - [singleton](https://platanus.kr/post/tag/singleton) - [prototype](https://platanus.kr/post/tag/prototype) - [bean scope](https://platanus.kr/post/tag/bean-scope) - [stack](https://platanus.kr/post/tag/stack) - [sort](https://platanus.kr/post/tag/sort) - [sorting](https://platanus.kr/post/tag/sorting) - [radix sort](https://platanus.kr/post/tag/radix-sort) - [indexing](https://platanus.kr/post/tag/indexing) - [proxy pattern](https://platanus.kr/post/tag/proxy-pattern) - [pointcut](https://platanus.kr/post/tag/pointcut) - [joinpoint](https://platanus.kr/post/tag/joinpoint) - [heap](https://platanus.kr/post/tag/heap) - [priority queue](https://platanus.kr/post/tag/priority-queue) - [deque](https://platanus.kr/post/tag/deque) - [prime](https://platanus.kr/post/tag/prime) - [assert](https://platanus.kr/post/tag/assert) - [Test Code](https://platanus.kr/post/tag/test-code) - [TDD](https://platanus.kr/post/tag/tdd) - [shortcut](https://platanus.kr/post/tag/shortcut) - [단축키](https://platanus.kr/post/tag/단축키) - [commit](https://platanus.kr/post/tag/commit) - [push](https://platanus.kr/post/tag/push) - [context](https://platanus.kr/post/tag/context) - [refactor](https://platanus.kr/post/tag/refactor) - [GetMapping](https://platanus.kr/post/tag/getmapping) - [PostMapping](https://platanus.kr/post/tag/postmapping) - [Spring Boot](https://platanus.kr/post/tag/spring-boot) - [H2 Database](https://platanus.kr/post/tag/h2-database) - [JDBC](https://platanus.kr/post/tag/jdbc) - [JdbcTemplate](https://platanus.kr/post/tag/jdbctemplate) - [ORM](https://platanus.kr/post/tag/orm) - [JPA](https://platanus.kr/post/tag/jpa) - [Spring Data JPA](https://platanus.kr/post/tag/spring-data-jpa) - [JPQL](https://platanus.kr/post/tag/jpql) - [Storage](https://platanus.kr/post/tag/storage) - [NAS](https://platanus.kr/post/tag/nas) - [Graphs](https://platanus.kr/post/tag/graphs) - [Weighted graphs](https://platanus.kr/post/tag/weighted-graphs) - [NoSQL](https://platanus.kr/post/tag/nosql) - [Insertion sort](https://platanus.kr/post/tag/insertion-sort) - [Merge sort](https://platanus.kr/post/tag/merge-sort) - [WAS](https://platanus.kr/post/tag/was) - [http](https://platanus.kr/post/tag/http) - [ERD](https://platanus.kr/post/tag/erd) - [E-R](https://platanus.kr/post/tag/e-r) - [Relationship](https://platanus.kr/post/tag/relationship) - [Relation](https://platanus.kr/post/tag/relation) - [Key](https://platanus.kr/post/tag/key) - [Primary key](https://platanus.kr/post/tag/primary-key) - [Foreign key](https://platanus.kr/post/tag/foreign-key) - [Database design](https://platanus.kr/post/tag/database-design) - [MVC](https://platanus.kr/post/tag/mvc) - [Spring Web](https://platanus.kr/post/tag/spring-web) - [Normalization](https://platanus.kr/post/tag/normalization) - [Transaction](https://platanus.kr/post/tag/transaction) - [ACID](https://platanus.kr/post/tag/acid) - [Atomicity](https://platanus.kr/post/tag/atomicity) - [Consistency](https://platanus.kr/post/tag/consistency) - [Durability](https://platanus.kr/post/tag/durability) - [DFS](https://platanus.kr/post/tag/dfs) - [BFS](https://platanus.kr/post/tag/bfs) - [Reflection](https://platanus.kr/post/tag/reflection) - [@Transactional](https://platanus.kr/post/tag/transactional) - [RESTful](https://platanus.kr/post/tag/restful) - [REST](https://platanus.kr/post/tag/rest) - [REST API](https://platanus.kr/post/tag/rest-api) - [CRUD](https://platanus.kr/post/tag/crud) - [Representation](https://platanus.kr/post/tag/representation) - [Stateless](https://platanus.kr/post/tag/stateless) - [Stateful](https://platanus.kr/post/tag/stateful) - [SOAP](https://platanus.kr/post/tag/soap) - [Build tool](https://platanus.kr/post/tag/build-tool) - [POM](https://platanus.kr/post/tag/pom) - [Groovy](https://platanus.kr/post/tag/groovy) - [Container](https://platanus.kr/post/tag/container) - [Docker](https://platanus.kr/post/tag/docker) - [Implement](https://platanus.kr/post/tag/implement) - [Generics](https://platanus.kr/post/tag/generics) - [Extends](https://platanus.kr/post/tag/extends) - [Abst](https://platanus.kr/post/tag/abst) - [Strategy](https://platanus.kr/post/tag/strategy) - [Logback](https://platanus.kr/post/tag/logback) - [Log4JDBC](https://platanus.kr/post/tag/log4jdbc) - [slf4j](https://platanus.kr/post/tag/slf4j) - [Log4j](https://platanus.kr/post/tag/log4j) - [Interceptor](https://platanus.kr/post/tag/interceptor) - [Strategy pattern](https://platanus.kr/post/tag/strategy-pattern) - [C](https://platanus.kr/post/tag/c) - [Collection framework](https://platanus.kr/post/tag/collection-framework) - [Collection](https://platanus.kr/post/tag/collection) - [Collection interface](https://platanus.kr/post/tag/collection-interface) - [ArrayList](https://platanus.kr/post/tag/arraylist) - [Vector](https://platanus.kr/post/tag/vector) - [Iterator](https://platanus.kr/post/tag/iterator) - [Set](https://platanus.kr/post/tag/set) - [HashSet](https://platanus.kr/post/tag/hashset) - [TreeSet](https://platanus.kr/post/tag/treeset) - [singleton pattern](https://platanus.kr/post/tag/singleton-pattern) - [exception](https://platanus.kr/post/tag/exception) - [Multipart](https://platanus.kr/post/tag/multipart) - [string](https://platanus.kr/post/tag/string) - [array](https://platanus.kr/post/tag/array) - [read-only data](https://platanus.kr/post/tag/read-only-data) - [C Programming Language](https://platanus.kr/post/tag/c-programming-language) - [strcat](https://platanus.kr/post/tag/strcat) - [strncat](https://platanus.kr/post/tag/strncat) - [strcpy](https://platanus.kr/post/tag/strcpy) - [strncpy](https://platanus.kr/post/tag/strncpy) - [strcmp](https://platanus.kr/post/tag/strcmp) - [strncmp](https://platanus.kr/post/tag/strncmp) - [strstr](https://platanus.kr/post/tag/strstr) - [strlen](https://platanus.kr/post/tag/strlen) - [multiple pointer](https://platanus.kr/post/tag/multiple-pointer) - [문자열](https://platanus.kr/post/tag/문자열) - [배열](https://platanus.kr/post/tag/배열) - [포인터](https://platanus.kr/post/tag/포인터) - [이중포인터](https://platanus.kr/post/tag/이중포인터) - [다중포인터](https://platanus.kr/post/tag/다중포인터) - [배열포인터](https://platanus.kr/post/tag/배열포인터) - [배열조작](https://platanus.kr/post/tag/배열조작) - [포인터조작](https://platanus.kr/post/tag/포인터조작) - [포인터순회](https://platanus.kr/post/tag/포인터순회) - [메모리](https://platanus.kr/post/tag/메모리) - [문자열처리](https://platanus.kr/post/tag/문자열처리) - [struct pointer](https://platanus.kr/post/tag/struct-pointer) - [구조체 포인터](https://platanus.kr/post/tag/구조체-포인터) - [스테이트 패턴](https://platanus.kr/post/tag/스테이트-패턴) - [state pattern](https://platanus.kr/post/tag/state-pattern) - [state](https://platanus.kr/post/tag/state) - [42](https://platanus.kr/post/tag/42) - [ecole 42](https://platanus.kr/post/tag/ecole-42) - [42 서울](https://platanus.kr/post/tag/42-서울) - [piscine](https://platanus.kr/post/tag/piscine) - [피신](https://platanus.kr/post/tag/피신) - [command pattern](https://platanus.kr/post/tag/command-pattern) - [커맨드 패턴](https://platanus.kr/post/tag/커맨드-패턴) - [디자인 패턴](https://platanus.kr/post/tag/디자인-패턴) - [옵저버 패턴](https://platanus.kr/post/tag/옵저버-패턴) - [observer](https://platanus.kr/post/tag/observer) - [observer pattern](https://platanus.kr/post/tag/observer-pattern) - [servlet](https://platanus.kr/post/tag/servlet) - [Map interface](https://platanus.kr/post/tag/map-interface) - [HashMap](https://platanus.kr/post/tag/hashmap) - [TreeMap](https://platanus.kr/post/tag/treemap) - [Template Method pattern](https://platanus.kr/post/tag/template-method-pattern) - [템플릿메소드 패턴](https://platanus.kr/post/tag/템플릿메소드-패턴) - [Operating System Concepts Essentials](https://platanus.kr/post/tag/operating-system-concepts-essentials) - [운영체제](https://platanus.kr/post/tag/운영체제) - [OSCE](https://platanus.kr/post/tag/osce) - [OSC](https://platanus.kr/post/tag/osc) - [운영체제 구조](https://platanus.kr/post/tag/운영체제-구조) - [System calls](https://platanus.kr/post/tag/system-calls) - [Inner Class](https://platanus.kr/post/tag/inner-class) - [내부 클래스](https://platanus.kr/post/tag/내부-클래스) - [인스턴스 내부 클래스](https://platanus.kr/post/tag/인스턴스-내부-클래스) - [정적 내부 클래스](https://platanus.kr/post/tag/정적-내부-클래스) - [지역 내부 클래스](https://platanus.kr/post/tag/지역-내부-클래스) - [익명 내부 클래스](https://platanus.kr/post/tag/익명-내부-클래스) - [서블릿](https://platanus.kr/post/tag/서블릿) - [컨테이너](https://platanus.kr/post/tag/컨테이너) - [JSP](https://platanus.kr/post/tag/jsp) - [doGet](https://platanus.kr/post/tag/doget) - [doPost](https://platanus.kr/post/tag/dopost) - [Factory Method Pattern](https://platanus.kr/post/tag/factory-method-pattern) - [팩토리 메소드 패턴](https://platanus.kr/post/tag/팩토리-메소드-패턴) - [싱글톤 패턴](https://platanus.kr/post/tag/싱글톤-패턴) - [스트레티지 패턴](https://platanus.kr/post/tag/스트레티지-패턴) - [Abstract Factory Pattern](https://platanus.kr/post/tag/abstract-factory-pattern) - [추상 팩토리 패턴](https://platanus.kr/post/tag/추상-팩토리-패턴) - [Stream](https://platanus.kr/post/tag/stream) - [Filter()](https://platanus.kr/post/tag/filter) - [forEach()](https://platanus.kr/post/tag/foreach) - [reduce()](https://platanus.kr/post/tag/reduce) - [Throws](https://platanus.kr/post/tag/throws) - [Composite pattern](https://platanus.kr/post/tag/composite-pattern) - [컴포짓 패턴](https://platanus.kr/post/tag/컴포짓-패턴) - [컴포지트 패턴](https://platanus.kr/post/tag/컴포지트-패턴) - [DataSource](https://platanus.kr/post/tag/datasource) - [JNDI](https://platanus.kr/post/tag/jndi) - [IPC](https://platanus.kr/post/tag/ipc) - [RPC](https://platanus.kr/post/tag/rpc) - [Pipe](https://platanus.kr/post/tag/pipe) - [프로세스](https://platanus.kr/post/tag/프로세스) - [Process](https://platanus.kr/post/tag/process) - [socket](https://platanus.kr/post/tag/socket) - [Shared memory](https://platanus.kr/post/tag/shared-memory) - [Message](https://platanus.kr/post/tag/message) - [공유 메모리](https://platanus.kr/post/tag/공유-메모리) - [메시지 전달](https://platanus.kr/post/tag/메시지-전달) - [PID](https://platanus.kr/post/tag/pid) - [Scheduling](https://platanus.kr/post/tag/scheduling) - [Scheduling queue](https://platanus.kr/post/tag/scheduling-queue) - [PCB](https://platanus.kr/post/tag/pcb) - [Process state](https://platanus.kr/post/tag/process-state) - [io](https://platanus.kr/post/tag/io) - [Thread](https://platanus.kr/post/tag/thread) - [fork](https://platanus.kr/post/tag/fork) - [Thread pool](https://platanus.kr/post/tag/thread-pool) - [serialization](https://platanus.kr/post/tag/serialization) - [file i/o](https://platanus.kr/post/tag/file-i-o) - [Object class](https://platanus.kr/post/tag/object-class) - [toString](https://platanus.kr/post/tag/tostring) - [equals](https://platanus.kr/post/tag/equals) - [hashCode](https://platanus.kr/post/tag/hashcode) - [clone](https://platanus.kr/post/tag/clone) - [StringBuffer](https://platanus.kr/post/tag/stringbuffer) - [StringBuilder](https://platanus.kr/post/tag/stringbuilder) - [process synchronization](https://platanus.kr/post/tag/process-synchronization) - [프로세스 동기화](https://platanus.kr/post/tag/프로세스-동기화) - [mutex lock](https://platanus.kr/post/tag/mutex-lock) - [mutex](https://platanus.kr/post/tag/mutex) - [뮤텍스](https://platanus.kr/post/tag/뮤텍스) - [Semaphores](https://platanus.kr/post/tag/semaphores) - [세마포어](https://platanus.kr/post/tag/세마포어) - [Deadlock](https://platanus.kr/post/tag/deadlock) - [교착상태](https://platanus.kr/post/tag/교착상태) - [philosopher](https://platanus.kr/post/tag/philosopher) - [식사하는 철학자](https://platanus.kr/post/tag/식사하는-철학자) - [CPU Scheduling](https://platanus.kr/post/tag/cpu-scheduling) - [dispatcher](https://platanus.kr/post/tag/dispatcher) - [FCFS](https://platanus.kr/post/tag/fcfs) - [SJF](https://platanus.kr/post/tag/sjf) - [Round Robin](https://platanus.kr/post/tag/round-robin) - [Memory](https://platanus.kr/post/tag/memory) - [shared library](https://platanus.kr/post/tag/shared-library) - [공유 라이브러리](https://platanus.kr/post/tag/공유-라이브러리) - [swap](https://platanus.kr/post/tag/swap) - [스왑](https://platanus.kr/post/tag/스왑) - [segmentation](https://platanus.kr/post/tag/segmentation) - [단편화](https://platanus.kr/post/tag/단편화) - [paging](https://platanus.kr/post/tag/paging) - [페이징](https://platanus.kr/post/tag/페이징) - [Page table](https://platanus.kr/post/tag/page-table) - [페이지 테이블](https://platanus.kr/post/tag/페이지-테이블) - [Virtual Memory](https://platanus.kr/post/tag/virtual-memory) - [가상 메모리](https://platanus.kr/post/tag/가상-메모리) - [Demand paging](https://platanus.kr/post/tag/demand-paging) - [요구 페이징](https://platanus.kr/post/tag/요구-페이징) - [Copy-on-Write](https://platanus.kr/post/tag/copy-on-write) - [페이지 교체](https://platanus.kr/post/tag/페이지-교체) - [FIFO](https://platanus.kr/post/tag/fifo) - [LRU](https://platanus.kr/post/tag/lru) - [프레임 할당](https://platanus.kr/post/tag/프레임-할당) - [NUMA](https://platanus.kr/post/tag/numa) - [Thrashing](https://platanus.kr/post/tag/thrashing) - [스레싱](https://platanus.kr/post/tag/스레싱) - [Page fault](https://platanus.kr/post/tag/page-fault) - [페이지폴트](https://platanus.kr/post/tag/페이지폴트) - [자바](https://platanus.kr/post/tag/자바) - [restore](https://platanus.kr/post/tag/restore) - [recovery](https://platanus.kr/post/tag/recovery) - [복구](https://platanus.kr/post/tag/복구) - [파일시스템](https://platanus.kr/post/tag/파일시스템) - [fsck](https://platanus.kr/post/tag/fsck) - [vgchange](https://platanus.kr/post/tag/vgchange) - [vgcfgrestore](https://platanus.kr/post/tag/vgcfgrestore) - [캐시복구](https://platanus.kr/post/tag/캐시복구) - [캐시탈거](https://platanus.kr/post/tag/캐시탈거) - [캐시깨짐](https://platanus.kr/post/tag/캐시깨짐) - [MyBatis](https://platanus.kr/post/tag/mybatis) - [마이바티스](https://platanus.kr/post/tag/마이바티스) - [Annotation](https://platanus.kr/post/tag/annotation) - [어노테이션](https://platanus.kr/post/tag/어노테이션) - [SQL](https://platanus.kr/post/tag/sql) - [MySQL](https://platanus.kr/post/tag/mysql) - [MariaDB](https://platanus.kr/post/tag/mariadb) - [GitHub](https://platanus.kr/post/tag/github) - [GitHub Actions](https://platanus.kr/post/tag/github-actions) - [CI/CD](https://platanus.kr/post/tag/ci-cd) - [workflow](https://platanus.kr/post/tag/workflow) - [ssh](https://platanus.kr/post/tag/ssh) - [bash script](https://platanus.kr/post/tag/bash-script) - [git](https://platanus.kr/post/tag/git) - [git flow](https://platanus.kr/post/tag/git-flow) - [cherry-pick](https://platanus.kr/post/tag/cherry-pick) - [reset HARD](https://platanus.kr/post/tag/reset-hard) - [checkout](https://platanus.kr/post/tag/checkout) - [branch](https://platanus.kr/post/tag/branch) - [Prepared Statement](https://platanus.kr/post/tag/prepared-statement) - [HttpSession](https://platanus.kr/post/tag/httpsession) - [Intercep](https://platanus.kr/post/tag/intercep) - [SimpleJdbcInsert](https://platanus.kr/post/tag/simplejdbcinsert) - [Argument resolver](https://platanus.kr/post/tag/argument-resolver) - [Request Mapping Handler Adapter](https://platanus.kr/post/tag/request-mapping-handler-adapter) - [한빛미디어](https://platanus.kr/post/tag/한빛미디어) - [한빛](https://platanus.kr/post/tag/한빛) - [Javascript](https://platanus.kr/post/tag/javascript) - [자바스크립트](https://platanus.kr/post/tag/자바스크립트) - [모던 자바스크립트](https://platanus.kr/post/tag/모던-자바스크립트) - [ES6](https://platanus.kr/post/tag/es6) - [책리뷰](https://platanus.kr/post/tag/책리뷰) - [책소개](https://platanus.kr/post/tag/책소개) - [서평](https://platanus.kr/post/tag/서평) - [prometheus](https://platanus.kr/post/tag/prometheus) - [zipkin](https://platanus.kr/post/tag/zipkin) - [istio](https://platanus.kr/post/tag/istio) - [spinnaker](https://platanus.kr/post/tag/spinnaker) - [metric](https://platanus.kr/post/tag/metric) - [msa](https://platanus.kr/post/tag/msa) - [sre](https://platanus.kr/post/tag/sre) - [distributed systems](https://platanus.kr/post/tag/distributed-systems) - [Wordpress](https://platanus.kr/post/tag/wordpress) - [SSL](https://platanus.kr/post/tag/ssl) - [TLS](https://platanus.kr/post/tag/tls) - [Mixed contents](https://platanus.kr/post/tag/mixed-contents) - [Reverse proxy](https://platanus.kr/post/tag/reverse-proxy) - [httpd](https://platanus.kr/post/tag/httpd) - [Apache](https://platanus.kr/post/tag/apache) - [NGINX](https://platanus.kr/post/tag/nginx) - [Really Simple SSL](https://platanus.kr/post/tag/really-simple-ssl) - [워드프레스](https://platanus.kr/post/tag/워드프레스) - [보안](https://platanus.kr/post/tag/보안) - [인증서](https://platanus.kr/post/tag/인증서) - [Domain](https://platanus.kr/post/tag/domain) - [Domain Model](https://platanus.kr/post/tag/domain-model) - [Domain Driven Design](https://platanus.kr/post/tag/domain-driven-design) - [Aggregate](https://platanus.kr/post/tag/aggregate) - [CQRS](https://platanus.kr/post/tag/cqrs) - [도메인](https://platanus.kr/post/tag/도메인) - [도메인 주도 설계](https://platanus.kr/post/tag/도메인-주도-설계) - [애그리거트](https://platanus.kr/post/tag/애그리거트) - [모델링](https://platanus.kr/post/tag/모델링) - [트랜잭션](https://platanus.kr/post/tag/트랜잭션) - [제네릭](https://platanus.kr/post/tag/제네릭) - [데이터베이스](https://platanus.kr/post/tag/데이터베이스) - [쿼리](https://platanus.kr/post/tag/쿼리) - [Oracle](https://platanus.kr/post/tag/oracle) - [MS-SQL](https://platanus.kr/post/tag/ms-sql) - [SQL Server](https://platanus.kr/post/tag/sql-server) - [Software Architect](https://platanus.kr/post/tag/software-architect) - [Architecture](https://platanus.kr/post/tag/architecture) - [Cloud Native](https://platanus.kr/post/tag/cloud-native) - [pub-sub](https://platanus.kr/post/tag/pub-sub) - [kube](https://platanus.kr/post/tag/kube) - [Kubernetes](https://platanus.kr/post/tag/kubernetes) - [EDA](https://platanus.kr/post/tag/eda) - [생산자-소비자](https://platanus.kr/post/tag/생산자-소비자) - [Side-Car](https://platanus.kr/post/tag/side-car) - [Circuit breaker](https://platanus.kr/post/tag/circuit-breaker) - [IT](https://platanus.kr/post/tag/it) - [은탄환](https://platanus.kr/post/tag/은탄환) - [은제탄환](https://platanus.kr/post/tag/은제탄환) - [Silver Bullet](https://platanus.kr/post/tag/silver-bullet) - [코딩인터뷰](https://platanus.kr/post/tag/코딩인터뷰) - [코딩테스트](https://platanus.kr/post/tag/코딩테스트) - [코테](https://platanus.kr/post/tag/코테) - [혼공시리즈](https://platanus.kr/post/tag/혼공시리즈) - [컴퓨터구조](https://platanus.kr/post/tag/컴퓨터구조) - [Concurrency](https://platanus.kr/post/tag/concurrency) - [WebFlux](https://platanus.kr/post/tag/webflux) - [Non-Blocking](https://platanus.kr/post/tag/non-blocking) - [LazyLoading](https://platanus.kr/post/tag/lazyloading) - [Redis](https://platanus.kr/post/tag/redis) - [Spring Data Redis](https://platanus.kr/post/tag/spring-data-redis) - [파일업로드](https://platanus.kr/post/tag/파일업로드) - [조영호](https://platanus.kr/post/tag/조영호) - [오브젝트](https://platanus.kr/post/tag/오브젝트) - [객체지향](https://platanus.kr/post/tag/객체지향) - [설계](https://platanus.kr/post/tag/설계) - [결합도](https://platanus.kr/post/tag/결합도) - [책임](https://platanus.kr/post/tag/책임) - [응집도](https://platanus.kr/post/tag/응집도) - [협력](https://platanus.kr/post/tag/협력) - [객체](https://platanus.kr/post/tag/객체) - [은닉](https://platanus.kr/post/tag/은닉) - [상속](https://platanus.kr/post/tag/상속) - [다형성](https://platanus.kr/post/tag/다형성) - [추상화](https://platanus.kr/post/tag/추상화) - [인터페이스](https://platanus.kr/post/tag/인터페이스) - [합성](https://platanus.kr/post/tag/합성) - [역할](https://platanus.kr/post/tag/역할) - [메시지](https://platanus.kr/post/tag/메시지) - [INFORMATION PATTERN](https://platanus.kr/post/tag/information-pattern) - [캡슐화](https://platanus.kr/post/tag/캡슐화) - [단일 책임 원칙](https://platanus.kr/post/tag/단일-책임-원칙) - [OpenSSL](https://platanus.kr/post/tag/openssl) - [libssl](https://platanus.kr/post/tag/libssl) - [libcrypto](https://platanus.kr/post/tag/libcrypto) - [OpenSSL 3](https://platanus.kr/post/tag/openssl-3) - [Compile](https://platanus.kr/post/tag/compile) - [ldconfig](https://platanus.kr/post/tag/ldconfig) - [sshd](https://platanus.kr/post/tag/sshd) - [Singleton registry](https://platanus.kr/post/tag/singleton-registry) - [Application Context](https://platanus.kr/post/tag/application-context) - [IoC](https://platanus.kr/post/tag/ioc) - [책임주도설계](https://platanus.kr/post/tag/책임주도설계) - [GRASP](https://platanus.kr/post/tag/grasp) - [INFORMATION EXPERT](https://platanus.kr/post/tag/information-expert) - [LOW COUPLING](https://platanus.kr/post/tag/low-coupling) - [HIGH COHESION](https://platanus.kr/post/tag/high-cohesion) - [PROTECTED VARIATIONS](https://platanus.kr/post/tag/protected-variations) - [CREATOR](https://platanus.kr/post/tag/creator) - [리팩토링](https://platanus.kr/post/tag/리팩토링) - [몬스터 메서드](https://platanus.kr/post/tag/몬스터-메서드) - [사설인증서](https://platanus.kr/post/tag/사설인증서) - [RSA](https://platanus.kr/post/tag/rsa) - [DES](https://platanus.kr/post/tag/des) - [PEM](https://platanus.kr/post/tag/pem) - [암호화된 개인키](https://platanus.kr/post/tag/암호화된-개인키) - [변경](https://platanus.kr/post/tag/변경) - [책임 주도 설계](https://platanus.kr/post/tag/책임-주도-설계) - [유연성](https://platanus.kr/post/tag/유연성) - [분해](https://platanus.kr/post/tag/분해) - [메시지 전송](https://platanus.kr/post/tag/메시지-전송) - [퍼블릭 인터페이스](https://platanus.kr/post/tag/퍼블릭-인터페이스) - [오퍼레이션](https://platanus.kr/post/tag/오퍼레이션) - [시그니처](https://platanus.kr/post/tag/시그니처) - [메서드](https://platanus.kr/post/tag/메서드) - [디미터 법칙](https://platanus.kr/post/tag/디미터-법칙) - [기차 충돌](https://platanus.kr/post/tag/기차-충돌) - [부끄럼타는 코드](https://platanus.kr/post/tag/부끄럼타는-코드) - [명령-쿼리 분리](https://platanus.kr/post/tag/명령-쿼리-분리) - [루틴](https://platanus.kr/post/tag/루틴) - [프로시저](https://platanus.kr/post/tag/프로시저) - [함수](https://platanus.kr/post/tag/함수) - [명령](https://platanus.kr/post/tag/명령) - [불변성](https://platanus.kr/post/tag/불변성) - [참조 투명성](https://platanus.kr/post/tag/참조-투명성) - [부수효과](https://platanus.kr/post/tag/부수효과) - [Ansible](https://platanus.kr/post/tag/ansible) - [Automation](https://platanus.kr/post/tag/automation) - [인프라 자동화](https://platanus.kr/post/tag/인프라-자동화) - [Infrastructure](https://platanus.kr/post/tag/infrastructure) - [IaaS](https://platanus.kr/post/tag/iaas) - [Top-down](https://platanus.kr/post/tag/top-down) - [하향식](https://platanus.kr/post/tag/하향식) - [기능분해](https://platanus.kr/post/tag/기능분해) - [데이터 추상화](https://platanus.kr/post/tag/데이터-추상화) - [모듈](https://platanus.kr/post/tag/모듈) - [절차 추상화](https://platanus.kr/post/tag/절차-추상화) - [타입 추상화](https://platanus.kr/post/tag/타입-추상화) - [람다](https://platanus.kr/post/tag/람다) - [의존성](https://platanus.kr/post/tag/의존성) - [컨텍스트](https://platanus.kr/post/tag/컨텍스트) - [런타임 의존성](https://platanus.kr/post/tag/런타임-의존성) - [컴파일 의존성](https://platanus.kr/post/tag/컴파일-의존성) - [전이](https://platanus.kr/post/tag/전이) - [의존성 전이](https://platanus.kr/post/tag/의존성-전이) - [의존](https://platanus.kr/post/tag/의존) - [명시적인 의존성](https://platanus.kr/post/tag/명시적인-의존성) - [숨겨진 의존성](https://platanus.kr/post/tag/숨겨진-의존성) - [컴퓨터 구조](https://platanus.kr/post/tag/컴퓨터-구조) - [Assembly Language](https://platanus.kr/post/tag/assembly-language) - [Concurrent](https://platanus.kr/post/tag/concurrent) - [Concurrent Programming](https://platanus.kr/post/tag/concurrent-programming) - [CPU](https://platanus.kr/post/tag/cpu) - [생성 사용 분리](https://platanus.kr/post/tag/생성-사용-분리) - [표현적 분해](https://platanus.kr/post/tag/표현적-분해) - [행위적 분해](https://platanus.kr/post/tag/행위적-분해) - [개방-폐쇄 원칙](https://platanus.kr/post/tag/개방-폐쇄-원칙) - [Dependency Inversion Principle](https://platanus.kr/post/tag/dependency-inversion-principle) - [의존성 주입](https://platanus.kr/post/tag/의존성-주입) - [의존 역전](https://platanus.kr/post/tag/의존-역전) - [GPT](https://platanus.kr/post/tag/gpt) - [ChatGPT](https://platanus.kr/post/tag/chatgpt) - [Application](https://platanus.kr/post/tag/application) - [중간점검](https://platanus.kr/post/tag/중간점검) - [중복코드](https://platanus.kr/post/tag/중복코드) - [DRY원칙](https://platanus.kr/post/tag/dry원칙) - [부모](https://platanus.kr/post/tag/부모) - [자식](https://platanus.kr/post/tag/자식) - [Class Object](https://platanus.kr/post/tag/class-object) - [Constructor](https://platanus.kr/post/tag/constructor) - [생성자](https://platanus.kr/post/tag/생성자) - [제네릭 메소드](https://platanus.kr/post/tag/제네릭-메소드) - [Generic Method](https://platanus.kr/post/tag/generic-method) - [Default 생성자](https://platanus.kr/post/tag/default-생성자) - [함수형 프로그래밍](https://platanus.kr/post/tag/함수형-프로그래밍) - [Functional Interface](https://platanus.kr/post/tag/functional-interface) - [Spliterator](https://platanus.kr/post/tag/spliterator) - [Parallel Stream](https://platanus.kr/post/tag/parallel-stream) - [병렬 스트림](https://platanus.kr/post/tag/병렬-스트림) - [CompletableFuture](https://platanus.kr/post/tag/completablefuture) - [Unmodifiable](https://platanus.kr/post/tag/unmodifiable) - [Lambda](https://platanus.kr/post/tag/lambda) - [SAM](https://platanus.kr/post/tag/sam) - [HAProxy](https://platanus.kr/post/tag/haproxy) - [HA](https://platanus.kr/post/tag/ha) - [Data Plane API](https://platanus.kr/post/tag/data-plane-api) - [Service status](https://platanus.kr/post/tag/service-status) - [Health check](https://platanus.kr/post/tag/health-check) - [method override](https://platanus.kr/post/tag/method-override) - [메소드 오버라이딩](https://platanus.kr/post/tag/메소드-오버라이딩) - [Tidy First?](https://platanus.kr/post/tag/tidy-first) - [켄트 벡](https://platanus.kr/post/tag/켄트-벡) - [메트릭](https://platanus.kr/post/tag/메트릭) - [관찰가능성](https://platanus.kr/post/tag/관찰가능성) - [데브옵스](https://platanus.kr/post/tag/데브옵스) - [모니터링](https://platanus.kr/post/tag/모니터링) - [강글리아](https://platanus.kr/post/tag/강글리아) - [OpenTelemetry](https://platanus.kr/post/tag/opentelemetry) - [프로메테우스](https://platanus.kr/post/tag/프로메테우스) - [예거](https://platanus.kr/post/tag/예거) - [DevOps](https://platanus.kr/post/tag/devops) - [파이썬](https://platanus.kr/post/tag/파이썬) - [fastapi](https://platanus.kr/post/tag/fastapi) - [Django](https://platanus.kr/post/tag/django) - [Flask](https://platanus.kr/post/tag/flask) - [Asynchronous](https://platanus.kr/post/tag/asynchronous) - [비동기](https://platanus.kr/post/tag/비동기) - [DB](https://platanus.kr/post/tag/db) - [Backend](https://platanus.kr/post/tag/backend) - [Web Application](https://platanus.kr/post/tag/web-application) - [클린 코드](https://platanus.kr/post/tag/클린-코드) - [Clean Code Cookbook](https://platanus.kr/post/tag/clean-code-cookbook) - [개념 모델링](https://platanus.kr/post/tag/개념-모델링) - [유스케이스](https://platanus.kr/post/tag/유스케이스) - [프로젝트 관리](https://platanus.kr/post/tag/프로젝트-관리) - [쿠버네티스](https://platanus.kr/post/tag/쿠버네티스) - [업캐스팅](https://platanus.kr/post/tag/업캐스팅) - [동적바인딩](https://platanus.kr/post/tag/동적바인딩) - [커리어](https://platanus.kr/post/tag/커리어) - [AWS](https://platanus.kr/post/tag/aws) - [클라우드](https://platanus.kr/post/tag/클라우드) - [입문서](https://platanus.kr/post/tag/입문서) - [이지스퍼블리싱](https://platanus.kr/post/tag/이지스퍼블리싱) - [길벗](https://platanus.kr/post/tag/길벗) - [Functional Programming](https://platanus.kr/post/tag/functional-programming) - [DDT](https://platanus.kr/post/tag/ddt) - [Hexagonal Architecture](https://platanus.kr/post/tag/hexagonal-architecture) - [Kotlin](https://platanus.kr/post/tag/kotlin) - [그로킹알고리즘](https://platanus.kr/post/tag/그로킹알고리즘) - [Grokking Algorithms](https://platanus.kr/post/tag/grokking-algorithms) - [알고리즘](https://platanus.kr/post/tag/알고리즘) - [자료구조](https://platanus.kr/post/tag/자료구조) - [도커](https://platanus.kr/post/tag/도커) - [릴레이](https://platanus.kr/post/tag/릴레이) - [Octet-Stream](https://platanus.kr/post/tag/octet-stream) - [MCP](https://platanus.kr/post/tag/mcp) - [OpenStack](https://platanus.kr/post/tag/openstack) - [아키텍트](https://platanus.kr/post/tag/아키텍트) - [Software Architecture](https://platanus.kr/post/tag/software-architecture) - [아키텍처](https://platanus.kr/post/tag/아키텍처) - [php](https://platanus.kr/post/tag/php) - [php-fpm](https://platanus.kr/post/tag/php-fpm) - [VPN](https://platanus.kr/post/tag/vpn) - [OpenConnect](https://platanus.kr/post/tag/openconnect) - [DNS](https://platanus.kr/post/tag/dns) - [unbound](https://platanus.kr/post/tag/unbound) - [Opensource](https://platanus.kr/post/tag/opensource) - [resilience4j](https://platanus.kr/post/tag/resilience4j) - [Spring AI](https://platanus.kr/post/tag/spring-ai) - [AI](https://platanus.kr/post/tag/ai) - [RAG](https://platanus.kr/post/tag/rag) - [lilfoto](https://platanus.kr/post/tag/lilfoto) - [검색플랫폼](https://platanus.kr/post/tag/검색플랫폼) - [프로토타이핑](https://platanus.kr/post/tag/프로토타이핑) - [수요조사](https://platanus.kr/post/tag/수요조사) - [UIUX](https://platanus.kr/post/tag/uiux)