인터넷 속도를 측정하기 위해서 fast.com등 여러 사이트를 이용한다.
맥 터미널에서 명령어 하나로 간단하게 인터넷 속도를 측정할 수 있다.
networkQuality

'OS > MacOS' 카테고리의 다른 글
| 맥(mac)에서 텍스트 파일 인코딩 변경하기 (0) | 2024.01.15 |
|---|
인터넷 속도를 측정하기 위해서 fast.com등 여러 사이트를 이용한다.
맥 터미널에서 명령어 하나로 간단하게 인터넷 속도를 측정할 수 있다.
networkQuality

| 맥(mac)에서 텍스트 파일 인코딩 변경하기 (0) | 2024.01.15 |
|---|
윈도우를 사용하는 분들과 협업을 하다보면 윈도우에서 작성된 텍스트 파일이 UTF-8이 아닌 MS-949 (CP-949) 인코딩으로 작성된 파일을 받을 때가 있다. 국제 표준인 UTF-8을 이용해 주시면 감사하겠지만, 어쩔 수 없이 내가 인코딩을 변경 해 줘야 한다.
CP-949에서 UTF-8로 인코딩을 변경하는 것은 터미널에서 간단하게 처리 할 수 있다.
iconv -c -f {원본 인코딩} -t {변환 인코딩} {원본 파일} > {저장 파일}


| mac(맥)에서 인터넷 속도 측정하기 (0) | 2024.01.15 |
|---|
| 2025년 월급 구간 별 실수령액 표 (0) | 2025.03.25 |
|---|---|
| 2025년 연봉 실 수령액 표 (0) | 2025.01.19 |
| [PowerShell] 텍스트파일 분리 (0) | 2022.03.29 |
| SMTP 발송 혹은 수신시 발생하는 에러 코드 (0) | 2021.06.04 |
| [ETC TIP] Windows 환경에서 Tomcat Log 실시간 보기 (0) | 2021.03.15 |
Caching은 H/W, S/W 전반에 걸쳐 사용되는 기술이다.
DB - application 뿐 아니라 클라이언트나 CDN에서도 캐싱을 사용한다.
이 글에서는 DB - Web Application의 캐싱만 다룬다.
서비스 응답시간에 큰 영향을 미치는 부분은 주로 네트워크 통신과 DB I/O이다. 캐싱을 통하면 DB I/O로 인해 발생하는 오버헤드를 줄일 수 있다.
캐시는 빠른 응답과 비용 절약을 위해 사용하는 임시 데이터다.
캐시는 임시 데이터다. 따라서 캐시를 저장할 때 캐시가 만료되는 시간 (expire time || TTL; Time To Live)를 명시한다.
캐시는 해당 시간 내에서만 유효하고 만료 시간이 경과하면 사용할 수 없다.
캐시에 만료되는 시간을 두는 이유는 캐시가 실시간 데이터가 아니기 때문이다. 만약 원본 데이터가 바뀐다면 캐시된 내용도 바뀌어야 한다.
캐시를 사용하면 DB에서 데이터를 읽을 때 발생하는 I/O 오버헤드를 줄일 수 있다. 캐시는 보통 Redis와 같은 In-Memory DB를 사용한다.
In-Memory DB는 메모리를 사용하기 때문에 일반적인 RDBMS보다 데이터를 읽는 속도가 빠르다. 따라서 캐시는 DB에서 데이터를 읽는 것 보다 월등히 속도가 빠르다.
In-Memory DB를 사용하면 요청을 빠르게 처리할 수 있지만, 메모리 특성상 데이터 소실의 위험이 있다. 또한 메모리 사용은 비용이 발생하기 때문에 방대한 양의 데이터를 모두 메모리에 적재하는 것은 큰 비용이 든다.
따라서 데이터의 특성에 따라 DB와 캐시를 적절히 사용하는 것이 매우 중요하다. 캐싱 전략을 올바르게 수립하면 적은 비용으로 큰 퍼포먼스 향상을 기대할 수 있다.
어떤 데이터를 캐싱하는 것이 좋을지 생각해 보아야 한다. 캐싱하기 좋은 데이터의 특성은 다음과 같다.
자주 바뀌지 않는 데이터의 경우, 한 번 캐시로 저장하면 메모리에서 읽어 빠르게 사용가능하다.
원본 데이터가 바뀌면 캐시도 바뀌어야 한다. 자주 바뀌지 않는 데이터의 캐시는 오랫동안 사용이 가능하기 때문에 캐싱하는 것이 효율적이다.
자주 사용되는 데이터는 캐싱하기 좋다. 한 번 캐싱해 놓으면 캐시를 사용하여 다수의 요청을 효율적으로 처리할 수 있다.
다만, 자주 사용될 지라도 매번 결과 값이 다르면 오히려 캐싱하지 않는 것이 낫다. 만약 일정시간 동안 데이터가 변하지 않는 것이 보장되면 해당 시간만큼의 TTL로 짧은 캐시를 생성하면 된다.
예를 들어 검색처럼 새로 요청하더라도 일정 시간 동안 같은 결과가 반환되는 경우에 해당한다.
자주 같은 결과를 반환하는 데이터의 경우도 캐싱을 적용하기 좋다. 예를 들어 특정 arguments의 조합에 따라 결과가 일정한 경우 해당된다.
이런 경우는 각 arguments의 조합을 key로 연산 결과를 캐싱하면 된다.
무거운 연산이 반복적으로 계산되어야 한다면 연산의 특성에 맞게 결과를 캐시하는 것이 효율적이다.
또는 사전에 별도의 프로세스에서 작업을 수행하여 결과를 미리 캐싱해 놓을 수 있다.
이 밖에도 일반적인 쿼리나 연산보다 캐싱할 때의 비용이 더 적다면 캐싱을 사용할 수 있다.
로그 분석이나 프로파일링을 통해 캐시를 적용할 함수나 API를 찾을 수 있다. 그러나 모든 사항을 고려하여 캐싱을 적용할지, TTL은 얼마나 적용할지 등은 개발자의 선택이 중요하다.
캐시를 이용하게 되면 닥쳐오는 문제점이 바로 데이터 정합성의 문제이다. 같은 종류의 데이터라도 두 저장소에 저장된 값이 서로 다른 현상이 일어날 수 밖에 없는 것이다.
따라서 적절한 캐시 읽기 전략(Read Cache Strategy)과 캐시 쓰기 전략(Write Cache Strategy)를 통해, 캐시와 DB간의 데이터 불일치 문제를 극복하면서도 빠른 성능을 잃지 않게 하기위해 연구를 할 필요가 있다.
일반적으로 사용되는 기본적인 캐시 전략. 이 방식은 캐시에 장애가 발생하더라도 DB에 질의를 실행함으로 캐시 장애로 인한 서비스 문제는 대비할 수 있지만, Cache Store와 DB간 정합성 유지 문제가 발생할 수 있음.
반복적으로 동일 쿼리를 수행하는 서비스에 적합, 단건 호출 빈도가 높은 서비스에는 비적합.
이런 경우 DB에서 캐시로 데이터를 미리 넣어주는 작업을 하기도 하는데 이를 Cache Warming이라고 함.
Cache Aside 방식과 비슷하지만, Cache Store에 저장하는 주체가 Server인가 혹은 Data Store 자체인가의 차이가 있음.
직접적인 DB 접근을 최소화 하고, Read에 대한 소모되는 자원을 최소화할 수 있음.
하지만 캐시에 문제가 발생하는 경우 바로 서비스 중단이 되기 때문에 Cache Store의 Replication 또는 Cluster구성하여 가용성을 높여야 함.
데이터를 저장할 때 DB가 아닌 캐시에 먼저 저장하여 모아놓았다가 특정 시점마다 DB로 쓰는 방식으로 일종의 Queue 역할을 겸하게 됨.
캐시에 데이터를 모았다 한 번에 DB에 저장하기 때문에 DB 쓰기 횟수 비용과 부하를 줄일 수 있지만, 데이터를 옮기기 전에 캐시 장애가 발생하면 데이터 유실이 발생할 수 있다는 단점이 존재.
반대로 DB에 장애가 발생하더라고 지속적인 서비스 제공을 보장하기도 함.
Replication이나 Cluster 구조를 적용하면 Cache Store 서비스의 가용성을 높일 수 있고, Read Through와 결함하변 가장 최근에 업데이트 된 데이터를 항상 캐시에서 사용할 수 있음.
Cache Store와 DB에 동시에 반영하는 방식. 항상 동기화 되어 있고 항상 최신정보를 가지고 있다는 장접이 있음.
저장할 때마다 2개 과정을 거치기 때문에 상대적으로 느림.
Cache Miss가 발생하기 전에 DB에 저장된 데이터가 수정되었을 때, 사용자가 조회하는 Cache Store와 DB 간의 데이터 불일치 발생.
캐시를 구성하는 목적은 빠른 성능 확보와 데이터 전달에 있으며 데이터의 영속성 보장하기 위함은 아니다.
데이터의 영속성은 기존 RDBMS에 위임하고, 캐시는 데이터 읽기에 집중하는 것이 성능확보의 지침사항이다.
또한 Cache Store가 장애로 인해 다운 되었을 경우나 서비스가 불가능 할 경우에도 지속적인 서비스가 가능해야 한다. 이는 데이터가 결국 RDBMS에 동일하게 저장되고 유지된다는 점을 뒷바침 한다.
| 개발자 KPI 세우기 (2) | 2025.01.17 |
|---|---|
| Test Case 작성법 (0) | 2024.05.10 |
| 업무 우선 순위 정하기 (아이젠하워 매트릭스) (0) | 2024.01.16 |
| 레거시 프로젝트 유지보수시 개선 포인트 - 1 - (0) | 2023.03.06 |
| 성능과 가독성을 높이는 분기처리 방법 (0) | 2020.12.11 |
참고 페이지의 간소화 버전이다. 아주 조금의 신경을 쓰면 명확하게 전달되는 커밋 메세지를 작성할 수 있다.
<타입>[적용 범위(선택 사항)]: <설명>
[본문(선택 사항)]
[꼬리말(선택 사항)]
참고 : https://www.conventionalcommits.org/ko/v1.0.0/#%ea%b0%9c%ec%9a%94
| [GIT] 한 컴퓨터에서 Github 계정 여러개 사용하기 (0) | 2024.05.27 |
|---|---|
| [GIT] (0) | 2024.04.10 |
| [GIT] 브랜치, 커밋 간 다른 파일 목록 조회 (0) | 2022.04.05 |
| [GIT] remote branch 가져오기 (0) | 2022.04.05 |
| [TortoiseSVN] Disconnect 방법 (0) | 2021.09.10 |
아래 코드의 이벤트는 div에 할당되어 있지만, em이나 code 같은 자식 태그를 클릭해도 동작합니다.
<div onclick="console.log('click div');">
<em><code>EM</code></em>을 클릭했는데도, <code>div</code>에 할당된 핸들러가 동작합니다.</em>
</div>
한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작합니다.
가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작합니다.
3개의 요소가 FORM > DIV > P 형태로 중첩된 구조에 각각 핸들러가 할당되어 있습니다.
<form onclick="console.log('click form')">
FORM
<div onclick="console.log('click div')">
DIV
<br/>
<p onclick="console.log(p)">P</p>
</div>
</form>
가장 안쪽의 p를 클릭하면 순서대로 다음과 같은 일이 벌어집니다.
이런 동작 방식 때문에 p 요소를 클릭하면 p -> div -> form 순서로 3개의 콘솔 로그가 출력되는 것이조.
이런 흐름을 '이벤트 버블링'이라고 부릅니다.
이벤트가 제일 깊은 곳에 있는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 형세 입니다.
거의 모든 이벤트는 버블링 됩니다.
focus와 같이 버블링 되지 않는 이벤트도 있습니다.
부모 요소의 핸들러는 이벤트가 정확히 어디서 발생했는지 등에 대한 자세한 정보를 얻을 수 있습니다.
이벤트가 발생한 가장 안쪽의 요소는 타깃(target) 요소라고 불리고, event.target을 사용해 접근할 수 있습니다.
event.target과 this (event.currentTarget)은 다음과 같은 차이가 있습니다.
이벤트 버블링은 타깃 이벤트에서 시작해서 html 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생합니다.
몇몇 이벤트는 window 객체까지 거슬러 올라가기도 합니다. 이 때도 모든 핸들러가 호출됩니다.
핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 할 수 있습니다.event.stopPropagation()을 사용하면됩니다.
한 요소의 특정 이벤트를 처리하는 핸들러가 여러개인 상황에서, 핸들러 중 하나가 버블링을 멈추더라도 나머지 핸들러는 여전히 동작합니다.
event.stopPropagation()은 위쪽으로 일어나는 버블링은 막아주지만, 다른 핸들러들이 동작하는 건 막지 못합니다.
버블링을 멈추고, 요소에 할당된 다른 핸들러의 동작도 막으려면 event.stopImmediatePropagation()을 사용해야 합니다. 이 메소드를 사용하면 요소에 할당된 특정 이벤트를 처리하는 핸들러들이 모두 동작하지 않습니다.
버블링은 유용합니다. 버블링을 꼭 멈춰야 하는 명백한 상황이 아니면 버블링을 막지 마세요. 아키텍쳐를 잘 고려해서 진짜 막아야 하는 상황에서만 버블링을 막으세요.
event.stopPropagation()은 추후에 문제가 될 수 있는 상황을 만들어 낼 수 있습니다.
document.addEventListener('click', ...)을 사용합니다.이벤트 버블링을 막아야 하는 경우는 거의 없습니다.
버블링을 막아야 해결 되는 문제라면 커스텀 이벤트 등을 사용해 문제를 해결할 수 있습니다.
핸들러의 event 객체에 데이터를 저장해 다른 핸들러에서 읽을 수 있게 하면, 아래쪽에서 무슨 일이 일어나는지를 부모 요소의 핸들러에게 전달할 수 있으므로, 이 방법으로도 이벤트 버블링을 통제할 수 있습니다.
| [성능 측정] Google Lighthouse (0) | 2024.04.01 |
|---|---|
| Webpack과 Babel 그리고 Polyfill (0) | 2020.11.30 |
특정 기간 중, CPU 사용율이 높은 쿼리를 조회한다.
CPU 점유율이 높은 쿼리를 찾아서 튜닝하기 위해서 사용한다. 기본적으로 oracle에서 제공하는 view를 활용한다.
WITH REF_DATE AS (
/* 대상 기간 지정 */
SELECT
TO_DATE('20220401' || ' 000000', 'YYYYMMDD HH24MISS') AS BGN_DE
, TO_DATE('20230420' || ' 235959', 'YYYYMMDD HH24MISS') AS END_DE
FROM DUAL
)
SELECT
X.SQL_ID
, X.CPU_TIME
, X.EXECUTIONS_DELTA
, X.CPU_TIME_PER_EXECUTIONS
, DBMS_LOB.SUBSTR(SUBSTR(D.SQL_TEXT, 1, 200)) AS SQL_TEXT
, D.SQL_TEXT AS SQL_FULLTEXT
FROM (
SELECT
SQL.DBID
, SQL.SQL_ID
, SUM(SQL.CPU_TIME_DELTA) / 1000000 AS CPU_TIME
, SUM(SQL.EXECUTIONS_DELTA) AS EXECUTIONS_DELTA
, ROUND((SUM(SQL.CPU_TIME_DELTA) / 1000000) / DECODE(SUM(SQL.EXECUTIONS_DELTA), 0, 1, SUM(SQL.EXECUTIONS_DELTA)) / DECODE(SQL.PX_SERVERS_EXECS_DELTA, 0, 1, SQL.PX_SERVERS_EXECS_DELTA)) AS CPU_TIME_PER_EXECUTIONS
FROM DBA_HIST_SQLSTAT SQL
, (
SELECT
MIN(SNAP_ID) AS START_SNAP_ID
, MAX(SNAP_ID) AS END_SNAP_ID
, MIN(BEGIN_INTERVAL_TIME) AS BEGIN_INTERVAL_TIME
, MAX(END_INTERVAL_TIME) AS END_INTERVAL_TIME
FROM DBA_HIST_SNAPSHOT, REF_DATE
WHERE BEGIN_INTERVAL_TIME BETWEEN REF_DATE.BGN_DE
AND REF_DATE.END_DE
) SNAP
WHERE SQL.SNAP_ID BETWEEN SNAP.START_SNAP_ID AND SNAP.END_SNAP_ID
GROUP BY SQL.DBID, SQL.SQL_ID, SQL.PX_SERVERS_EXECS_DELTA
HAVING SUM(SQL.EXECUTIONS_DELTA) >= 0
ORDER BY CPU_TIME_PER_EXECUTIONS DESC
) X
INNER JOIN DBA_HIST_SQLTEXT D
ON D.SQL_ID = X.SQL_ID
AND D.DBID = X.DBID
WHERE ROWNUM <= 40
;
SELECT
SQL.DBID
, SUM(SQL.CPU_TIME_DELTA) / 1000000 AS CPU_TIME
, SUM(SQL.EXECUTIONS_DELTA) AS EXECUTIONS_DELTA
, ROUND((SUM(SQL.CPU_TIME_DELTA) / 1000000) / DECODE(SUM(SQL.EXECUTIONS_DELTA), 0, 1, SUM(SQL.EXECUTIONS_DELTA)) / DECODE(SQL.PX_SERVERS_EXECS_DELTA, 0, 1, SQL.PX_SERVERS_EXECS_DELTA)) AS CPU_TIME_PER_EXECUTIONS
FROM DBA_HIST_SQLSTAT SQL
, (
SELECT
MIN(SNAP_ID) AS START_SNAP_ID
, MAX(SNAP_ID) AS END_SNAP_ID
, MIN(BEGIN_INTERVAL_TIME) AS BEGIN_INTERVAL_TIME
, MAX(END_INTERVAL_TIME) AS END_INTERVAL_TIME
FROM DBA_HIST_SNAPSHOT
WHERE BEGIN_INTERVAL_TIME BETWEEN TO_DATE('20230401' || ' 000000', 'YYYYMMDD HH24MISS')
AND TO_DATE('20230419' || ' 235959', 'YYYYMMDD HH24MISS')
) SNAP
WHERE SQL.SNAP_ID BETWEEN SNAP.START_SNAP_ID AND SNAP.END_SNAP_ID
GROUP BY SQL.DBID, SQL.SQL_ID, SQL.PX_SERVERS_EXECS_DELTA
HAVING SUM(SQL.EXECUTIONS_DELTA) >= 0
ORDER BY CPU_TIME_PER_EXECUTIONS
;
SELECT
MIN(SNAP_ID) AS START_SNAP_ID
, MAX(SNAP_ID) AS END_SNAP_ID
, MIN(BEGIN_INTERVAL_TIME) AS BEGIN_INTERVAL_TIME
, MAX(END_INTERVAL_TIME) AS END_INTERVAL_TIME
FROM DBA_HIST_SNAPSHOT
WHERE BEGIN_INTERVAL_TIME BETWEEN TO_DATE('20230401' || ' 000000', 'YYYYMMDD HH24MISS')
AND TO_DATE('20230419' || ' 235959', 'YYYYMMDD HH24MISS')
;| [PostgreSQL] PostgreSQL AccessShareLock 이해 및 해제 가이드 (2) | 2024.11.19 |
|---|---|
| [PostgreSQL] 사용중인 function의 정의 내용을 특정 문자열 검색 하는 방법 (0) | 2024.11.15 |
| [DB] Oracle 쿼리 튜닝을 위한 쿼리 분석 방법 (0) | 2023.04.13 |
| [SQL] 오라클 조회 쿼리 성능 개선을 위한 정리 - 1 (0) | 2023.04.12 |
| 락 걸린 테이블 확인 및 락 해제 (0) | 2022.02.16 |
Head First Design Patterns는 객체지향 프로그래밍과 디자인 패턴에 대한 입문서다. 이 책 또한 다른 전공 서적과 다르게 쉽게 읽히는 책이다. 그림과 예제 코드를 통해 설명되며, 이러한 방식으로 개념을 쉽게 이해할 수 있었다.
"변하지 않는 사실은 계속 변화한다"라는 문장을 책에서 강조하는데, 현업에서 개발하다 보면 기획내용이나 사용자의 요구사항은 계속 변한다. 어제까지는 분명 A를 얘기했는데, 오늘 저녁에 갑자기 B나 C 또는 H로 요구사항이 바뀔 수 있다. 열심히 다 만들었더라도 요구사항이 추가되거나 변하면 새로운 것을 다시 만들어야 하는 상황이 흔한 것이다. 사실 요구사항의 변화는 SW의 본질이라고 할 수 있다. 그렇기에 변경에 용이한 아키텍쳐를 설계하고 개발하는 것이 개발자의 중요 역량이라고 생각한다. 그게 안 되면 IT로 밥 벌어먹으면 안 된다는 생각. 어쨌거나, 변경에 용이한 코드를 작성하기 위해서는 여러 가지 디자인 패턴이 있고, 예제를 패턴을 적용해 개선해 나가는 예시로 설명해준다.
책에서는 디자인 패턴의 개념과 각 패턴이 어떤 상황에서 사용되는지에 대해 설명한다. 디자인 패턴은 각각 객체 생성, 객체 구조, 인터페이스, 행위 등의 다양한 측면에서 소프트웨어 디자인을 개선하기 위한 것이다. 또한, 이 책은 디자인 패턴을 적용하는 과정에서 발생하는 문제와 해결 방법에 대해 다루며, 이를 통해 디자인 패턴을 적용하는 방법을 익힐 수 있도록 돕는다. 디자인 패턴은 사실 무궁무진하게 많다, java, c, javascript 언어에 따라서도 다른 패턴이 나온다. 이 책에서는 java 계열 실무에서 자주 사용하는 디자인 패턴을 집중해서 다뤄주고 있다. 책은 650여 페이지로 굉장히 두꺼운데, 그림이 대다수를 차지하고 있고, 독자의 가독성을 고려하여 쓴 책이라 쉽게 읽힌다. (글을 잘 쓰는 사람이 개발도 잘한다는 말을 반증하는 것 같다.)
나는 객체 지향을 조금 더 잘 활용해보고 싶은 개발자로 추상화, 캡슐화, 다형성, 상속을 어떻게 하면 더 잘 적용할 수 있을지를 이 책을 통해 심도있게 고민해보았다. 흔히들 코드 재사용을 막기 위해 상속을 사용하는데, 생각지 못한 상황에 반복된 코드를 짤 수밖에 없었던 적이 많다. 그런 상황에 대한 해법들도 이 책을 통해 얻었다.
Head First Design Patterns는 객체지향 프로그래밍과 디자인 패턴에 대한 이해를 쉽게 접근할 수 있도록 돕는다. 이 책으로 습득한 디자인 패턴을 사용하면 더 나은 소프트웨어 디자인을 구현할 수 있을 것으로 기대되고, 이는 개발자로서의 역량 향상에 큰 도움이 될 것 같다.
| [독후감] 테스트 주도 개발 실천법과 도구 (0) | 2023.04.13 |
|---|---|
| [독후감] 클린 코드 (1) | 2023.03.25 |
| [독후감] 읽기 좋은 코드가 좋은 코드다 (0) | 2023.03.06 |
| [독후감] 토비의 스프링 3.1 Vol.1 (0) | 2023.03.06 |
| 필독도서 (0) | 2022.07.13 |
채수원 님의 TDD(Test Driven Development) 개발 실천법과 도구는 소프트웨어 개발 방법론 중 하나인 TDD를 구체적으로 실천하는 방법과 그 과정에서 사용되는 도구들에 대한 내용을 다룬 책이다. TDD 대한 이해를 높이고 실제 개발에 적용하는 방법을 설명한다. TDD(Test Driven Development)는 소프트웨어 개발 방법론 중 하나로, 테스트 케이스를 먼저 작성하고 이를 통과하는 코드를 작성하는 것을 중심으로 개발하는 방법
책에서는 TDD의 개념과 원칙을 소개하며 테스트 케이스(TC) 작성, 코드 작성, 리팩토링 등의 단계별로 구체적인 예시를 보여준다. 특히 TC 작성과 이를 통한 코드 작성의 중요성에 대해 강조하며 TDD의 장점과 효과를 다양한 관점으로 보여준다. 책에서는 TDD를 실천하는 데 필요한 기본적인 원칙과 방법론을 설명하면서, 이를 구현하는 과정에서 발생하는 이슈와 해결 방법 등에 대해서도 다룬다. TDD를 적용하는 데에 있어 좋은 습관과 나쁜 습관을 비교하며 TDD를 대하는 개발자의 태도화 실천할 것들을 제시한다.
TDD를 실천하는 과정은 다음과 같다.
이런 과정을 반복하며 개발하는 것이 TDD의 핵심이다. 이 과정에서 개발자는 작성한 코드가 정상적으로 동작하는지 항상 확인할 수 있으며, 버그를 빠르게 발견하고 수정할 수 있다고. 또한, 작성한 코드를 리팩토링하면서 코드의 유지 보수성과 확장성을 높일 수 있다고 한다.
TDD를 실천하는 개발자들은 코드 품질과 안정성을 높일 수 있으며, 개발 프로세스를 보다 효율적으로 관리할 수 있다고 한다. 또한, TDD는 기능 구현 외에도 코드의 문서화와 같은 부가적인 기능을 제공할 수 있어, 소프트웨어 개발의 생산성을 높일 수 있다고 한다.
TDD를 처음 접하는 초심자에게 유용한 정보이지만 초판 이후 어른들의 사정으로 재판이 나오지 않았고, 옛날 기술이나 라이브러리에 대한 설명이 많다. TDD를 업무에서 실 사용해보지 않은 내 입장에서는 일단 겪어봐야 할 것 같다. SW 품질을 높이는데 철학이 없는 조직에서는 TDD를 적용하기가 쉽지 않아서, 어쩌면 뜬구름 잡는 소리로 보이는 것도 있을 것 같다. 그치만 나는 내 일을 하면서 SW 품질을 높이는 데 많은 목마름이 있기에 꼭 TDD를 경험해 봐야 할 것 같다. 일단 나는 사이드 프로젝트에서 TDD를 사용해야겠다.
| [독후감] 헤드퍼스트 디자인 패턴 (0) | 2023.04.14 |
|---|---|
| [독후감] 클린 코드 (1) | 2023.03.25 |
| [독후감] 읽기 좋은 코드가 좋은 코드다 (0) | 2023.03.06 |
| [독후감] 토비의 스프링 3.1 Vol.1 (0) | 2023.03.06 |
| 필독도서 (0) | 2022.07.13 |
오라클 DB의 예상 실행 계획만으로는 성능 개선에 어려움을 겪을 때가 있음. 실제 실행 계획을 보고 문제점을 진단할 수 있어야 함.gather_plan_statistics 힌트는 Oracle SQL에서 SQL 문의 실제 실행 통계를 수집할 수 있는 기능.
이 힌드를 사용하면 Oracle DB는 SQL 실행 계획의 각 단계에서 처리된 행 수, 사용된 메모리 양 및 각 단계에서 사용된 시간과 같은 자세한 통계를 수집함.
SQL 문에 다음과 같이 간단히 추가하면 됨.
SELECT /*+ gather_plan_statistics */ column1, column2, ...
FROM TABLE
WHERE ...
성능 문제를 진단하고 SQL 문을 최적화하는데 유용함./*+ gather_plan_statistics */ SQL을 실행한 후, DBMS_XPLAN.DISPLAY_CURSOR 함수를 사용하여 실행 계획과 관련된 통계를 볼 수 있음.DISPLAY_CURSOR 함수는 실행 계획과 통계의 자세한 보고서를 반환하므로 SQL 문의 성능을 분석하고 최적화할 부분을 식별하는 데 사용할 수 있음.
PREDICATE INFORMATION 섹션에서는 WHERE절과 JOIN 조건에 대한 추가 정보도 제공함
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT => 'ALLSTATS LAST'));
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS LAST'));
DISPLAY_CURSOR 매개 변수FORMAT=>'ALLSTATS LAST'를 사용하면 모든 실행계획 정보와 통계를 검색함.SQL_ID 찾기SQL_ID를 가져오기 위해 현재 DB에 접속한 SESSION에서 실행한 SQL 문의 히스토리를 검색하여 정보를 가져옴.
--------------------------------------------------------------------------------
-- SQL_ID, CHILD_NUMBER 추출
--------------------------------------------------------------------------------
SELECT
SA.SQL_ID,
S.CHILD_NUMBER,
SA.SQL_TEXT,
SA.MODULE,
SA.LAST_LOAD_TIME,
SA.LAST_ACTIVE_TIME,
SA.PLAN_HASH_VALUE,
SA.OPTIMIZER_COST,
SA.FETCHES,
SA.EXECUTIONS,
SA.cpu_time,
SA.ELAPSED_TIME,
S.DISK_READS,
S.PARSE_CALLS,
S.BUFFER_GETS,
S.ROWS_PROCESSED,
SA.PARSING_USER_ID,
SA.PARSING_SCHEMA_ID,
SA.PARSING_SCHEMA_NAME
FROM V$SQLAREA SA
/* V$SQLAREA : 공유 SQL 영역 */
INNER JOIN V$SESSION SS
/* V$SESSION : 현재 세션에 대한 정보 */
ON SA.PARSING_USER_ID = SS.USER#
AND SA.PARSING_SCHEMA_ID = SS.SCHEMA#
INNER JOIN V$SQL S
/* V$SQL : 공유 SQL 영역 내 쿼리에 대한 정보 */
ON SA.SQL_ID = S.SQL_ID
WHERE SS.AUDSID = USERENV('SESSIONID')
/* 현재 세션과 같은 SESSION ID */
AND SS.SID = USERENV('SID')
/* 특정 스키마 */
AND SA.PARSING_SCHEMA_NAME = 'IDLOOK'
/* 약 15분 이내에 실행한 쿼리만 조회 */
AND SA.LAST_ACTIVE_TIME >= SYSDATE - 0.01
/* 제외 */
AND sa.PARSING_SCHEMA_NAME NOT IN ('SYS', 'SYSTEM')
AND sa.SQL_TEXT NOT LIKE '%DBMS%'
AND sa.SQL_TEXT NOT LIKE '%V$%'
/* 실행 모듈이 운영 또는 타 시스템에서 실행한 쿼리라면 제외 */
AND SA.MODULE NOT IN ('DBMS_SCHEDULER', 'JDBC Thin Client', 'w3wp.exe')
/* 특정 문자열 제외*/
AND NOT REGEXP_LIKE(UPPER(SA.SQL_TEXT), 'V\$SQL|PLAN_TABLE|DBMS_XPLAN|EXTRACTVALUE\(|XMLSEQUENCE\(|CURRENT_SCHEMA|DBA_|DBMS_UTILITY|CONSTRAINT')
ORDER BY SA.LAST_ACTIVE_TIME DESC, SA.SQL_ID, S.CHILD_NUMBER
;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS LAST'));
쿼리 실행 시 권한 부족한 경우 DBA 계정으로 로그인하여 권한 부여 작업을 수행하거나 DBA 권한이 있는 사용자에게 권한을 부여해야 함.
DBMS_XPLAN.DISPLAY_CURSOR 함수를 사용하려면 V$SESSION, V$SQL_SESSION, V$SQL(OPTIONAL), V$SQL_PLAN_STATISTICS_ALL 권한이 필요. (해당 권한이 없는 경우 ORA-01031: insufficient privileges 오류가 발생)
STATISTICS_LEVEL PARAMETER 값을 ALL로 변경 한 경우ALTER SESSION SET STATISTICS_LEVEL = ALL;_ROWSOURCE_EXECUTION_STATISTICS PARAMETER 값을 TRUE로 변경한 경우GATHER_PLAN_STATISTICS HINT를 사용위의 헤더에서 튜닝 시 가장 중요하게 활용되는 부분은 Buffers, A-Rows.
Buffers 값을 통해서 Get Block의 총량을 알 수 있고, A-Rows를 통해 플랜 단계별로 실제 Row 수를 알 수 있음.
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('3YTNQSYC1PXJ8', NULL, 'ADVANCED ALLSTATS ALL -PROJECTION +ROWS +BYTES +PREDICATE'));

| [PostgreSQL] 사용중인 function의 정의 내용을 특정 문자열 검색 하는 방법 (0) | 2024.11.15 |
|---|---|
| [DB] 특정 기간중 DB CPU 부하가 높은 SQL 찾기 (0) | 2023.04.20 |
| [SQL] 오라클 조회 쿼리 성능 개선을 위한 정리 - 1 (0) | 2023.04.12 |
| 락 걸린 테이블 확인 및 락 해제 (0) | 2022.02.16 |
| [DB] INDEX REBUILD (0) | 2021.01.07 |