2026/04/12
오늘의 이야기
#billcorea #운동동아리관리앱
🏸 Schneedle, aplikasi mesti ada untuk kelab badminton!
👉 Main Perlawanan – Rekod Markah & Cari Lawan 🎉
Sesuai untuk mana-mana sahaja, bersendirian, bersama rakan-rakan atau dalam kelab! 🤝
Jika anda suka badminton, pasti mencubanya
Pergi ke aplikasi 👉 https://play.google.com/store/apps/details?id=com.billcorea.matchplay
오늘의 이야기
Oracle 해시 조인의 이해와 활용
데이터베이스에서 대용량 데이터를 효율적으로 조인하는 방법 중 하나는 해시 조인(Hash Join)입니다. 이 글에서는 Oracle 데이터베이스에서 해시 조인의 작동 방식과 성능 특성, 그리고 사용 시기에 대해 알아보겠습니다.
해시 조인의 작동 방식
해시 조인은 두 단계로 이루어집니다:
Build 단계: 작은 집합(Build Input)을 읽어 해시 테이블을 생성합니다. 이 해시 테이블은 메모리에 저장되며, 조인 키를 기준으로 해시 버킷에 데이터를 분류합니다.
Probe 단계: 큰 집합(Probe Input)을 읽어 해시 테이블을 탐색하면서 조인합니다. 각 레코드는 해시 테이블의 해당 버킷을 탐색하여 일치하는 레코드를 찾습니다.
성능 특성
해시 조인은 다음과 같은 성능 특성을 가집니다:
랜덤 액세스 부하 없음: 조인 과정에서 랜덤 액세스 부하가 발생하지 않아 성능이 향상됩니다.
메모리 사용: 주로 PGA(Process Global Area) 메모리를 사용하여 디스크 I/O를 최소화합니다.
CPU 및 메모리 의존성: 해시 테이블 생성과 탐색에 많은 CPU와 메모리 자원이 필요합니다.
해시 조인의 사용 시기
해시 조인은 다음과 같은 상황에서 유용합니다:
인덱스가 없는 경우: 조인 컬럼에 적당한 인덱스가 없을 때 해시 조인이 효과적입니다.
대용량 데이터 조인: 많은 양의 데이터를 조인해야 할 때 해시 조인이 유리합니다.
성능 개선 방법
해시 조인의 성능을 최적화하기 위해 다음과 같은 방법을 사용할 수 있습니다:
효율적인 해시 테이블 생성: Build Input이 충분히 작고 중복 값이 적어야 합니다.
충분한 메모리 확보: Hash Area에 충분한 메모리를 할당하여 디스크 I/O를 줄입니다.
예제 코드
다음은 Oracle에서 해시 조인을 사용하는 예제 코드입니다:
SQL
SELECT /*+ USE_HASH(o l) */
o.customer_id,
l.unit_price * l.quantity AS total_price
FROM
orders o,
order_items l
WHERE
o.order_id = l.order_id;
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
이 쿼리는 orders 테이블의 order_id와 order_items 테이블의 order_id를 해시 조인하여 각 고객의 총 주문 금액을 계산합니다.
이 글이 해시 조인에 대한 이해를 돕는 데 도움이 되었기를 바랍니다. 추가로 궁금한 점이 있으면 언제든지 댓글로 남겨주세요! 😊
오늘의 이야기
#스하리1000명프로젝트,
Kadang-kadang susah nak bercakap dengan pekerja asing kan?
Saya membuat aplikasi mudah yang membantu! Anda menulis dalam bahasa anda, dan orang lain melihatnya dalam bahasa mereka.
Ia auto-terjemah berdasarkan tetapan.
Sangat berguna untuk sembang mudah. Lihatlah apabila anda mendapat peluang!
https://play.google.com/store/apps/details?id=com.billcoreatech.multichat416
오늘의 이야기
리눅스 셸 스크립트로 날짜 생성하기
리눅스 셸 스크립트를 사용하여 향후 3개월 동안의 날짜 목록을 생성하는 방법에 대해 논의했습니다. 다음은 블로그 게시물에 사용할 수 있는 단계별 가이드와 최종 스크립트입니다.
단계별 가이드
- 시작 날짜와 종료 날짜 초기화:
- 시작 날짜는 오늘 날짜로 설정합니다.
- 종료 날짜는 오늘로부터 3개월 후로 계산합니다.
- 각 날짜를 반복:
- while 루프를 사용하여 시작 날짜부터 종료 날짜까지 각 날짜를 반복합니다.
- 원하는 형식(yyyymmdd)으로 각 날짜를 출력합니다.
- 날짜 비교:
- 숫자 비교를 위해 -lt를 사용하여 올바른 날짜 비교를 보장합니다.
최종 스크립트
다음은 향후 3개월 동안의 날짜를 yyyymmdd 형식으로 생성하는 최종 스크립트입니다:
#!/bin/bash
# 시작 날짜 (오늘)
start_date=$(date +%Y%m%d)
# 종료 날짜 (오늘로부터 3개월 후)
end_date=$(date -d "+3 months" +%Y%m%d)
# 시작 날짜부터 종료 날짜까지 각 날짜를 반복
current_date=$start_date
while [[ "$current_date" -lt "$end_date" ]]; do
echo $current_date
current_date=$(date -d "$current_date + 1 day" +%Y%m%d)
done
설명
- 시작 날짜: start_date=$(date +%Y%m%d)는 시작 날짜를 yyyymmdd 형식으로 초기화합니다.
- 종료 날짜: end_date=$(date -d "+3 months" +%Y%m%d)는 오늘로부터 3개월 후의 종료 날짜를 계산합니다.
- 루프: while 루프는 각 날짜를 반복하며 지정된 형식으로 날짜를 출력합니다.
이 스크립트는 날짜 시퀀스를 생성해야 하는 다양한 자동화 작업에 유용합니다. 필요에 따라 추가로 커스터마이즈할 수 있습니다!
이 내용이 블로그 게시물 작성에 도움이 되길 바랍니다! 더 필요한 정보나 도움이 필요하면 언제든지 말씀해 주세요.
오늘의 이야기
Python으로 BLE 장치와 통신하기
BLE(Bluetooth Low Energy) 장치와 통신하는 방법을 Python을 사용하여 구현해 보았습니다. 이 글에서는 BLE 장치를 검색하고, 서비스와 특성을 확인하며, 데이터를 주고받는 과정을 단계별로 설명합니다.
1. BLE 장치 검색
먼저, bleak 라이브러리를 사용하여 BLE 장치를 검색합니다. bleak는 Windows, macOS, Linux에서 모두 작동하는 BLE 라이브러리입니다.
설치
pip install bleak
코드
import asyncio
from bleak import BleakScanner
async def scan():
devices = await BleakScanner.discover()
for device in devices:
print(device)
asyncio.run(scan())
이 코드는 BLE 장치를 검색하고, 검색된 장치 목록을 출력합니다.
2. BLE 장치의 서비스 및 특성 확인
검색된 장치의 서비스와 특성을 확인하기 위해 bleak 라이브러리를 사용합니다.
코드
import asyncio
from bleak import BleakClient
address = "F6:5B:9F:64:41:37" # BLE 장치의 주소
async def get_services(address):
async with BleakClient(address) as client:
services = client.services
for service in services:
print(f"Service: {service.uuid}")
for characteristic in service.characteristics:
print(f" Characteristic: {characteristic.uuid}")
asyncio.run(get_services(address))
이 코드는 특정 BLE 장치에 연결하여 모든 서비스와 특성의 UUID를 출력합니다.
3. 데이터 전송 및 수신
BLE 장치와 데이터를 주고받기 위해 bleak 라이브러리를 사용합니다.
코드
import asyncio
from bleak import BleakClient
address = "F6:5B:9F:64:41:37"
RX_CHARACTERISTIC_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" # 데이터 전송
TX_CHARACTERISTIC_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" # 데이터 수신
async def send_data(client, data):
await client.write_gatt_char(RX_CHARACTERISTIC_UUID, data)
print(f"Sent: {data}")
async def receive_data(client):
def notification_handler(sender, data):
print(f"Received: {data}")
await client.start_notify(TX_CHARACTERISTIC_UUID, notification_handler)
await asyncio.sleep(5) # 데이터 수신 대기 시간
await client.stop_notify(TX_CHARACTERISTIC_UUID)
async def main():
async with BleakClient(address) as client:
if client.is_connected:
print(f"Connected to {address}")
# 데이터 전송
await send_data(client, b'Hello BLE')
# 데이터 수신
await receive_data(client)
asyncio.run(main())
이 코드는 BLE 장치에 연결하여 데이터를 전송하고 수신하는 방법을 보여줍니다. 수신된 데이터는 notification_handler를 통해 출력됩니다.
4. 수신된 데이터 해석
수신된 데이터는 다음과 같은 형식으로 출력됩니다:
Received: bytearray(b'3639,-276\n')
Received: bytearray(b'3673,-435\n')
...
이 데이터를 해석하려면 장치의 프로토콜 문서나 데이터 형식을 참조해야 합니다. 예를 들어, 숫자 쌍 데이터를 파싱하는 코드는 다음과 같습니다:
data = bytearray(b'3639,-276\n')
values = data.decode('utf-8').strip().split(',')
x, y = int(values[0]), int(values[1])
print(f"x: {x}, y: {y}")
이 코드를 사용하면 수신된 데이터를 적절히 파싱하여 의미 있는 값으로 변환할 수 있습니다.
이 글을 통해 Python을 사용하여 BLE 장치와 통신하는 방법을 이해하고, 실제로 데이터를 주고받는 과정을 구현해 보았습니다. 추가로 궁금한 점이 있거나 도움이 필요하시면 언제든지 댓글로 남겨주세요! 😊
오늘의 이야기
디버그 모드에서 가짜 Bluetooth 스캔 결과 시뮬레이션하기
안드로이드 개발 중 Bluetooth 기능을 테스트할 때, 실제 장치가 없거나 테스트 환경을 조작하고 싶을 때가 있습니다. 이 글에서는 no.nordicsemi.android.support.v18.scanner.ScanCallback을 사용하여 디버그 모드에서 가짜 Bluetooth 스캔 결과를 시뮬레이션하는 방법을 소개합니다.
1. Mock 데이터 생성
먼저, ScanResult와 ScanRecord를 포함한 Mock 데이터를 생성합니다.
Kotlin
import no.nordicsemi.android.support.v18.scanner.ScanCallback
import no.nordicsemi.android.support.v18.scanner.ScanResult
import android.bluetooth.BluetoothDevice
import android.bluetooth.le.ScanRecord
import java.lang.reflect.Constructor
// Mock BluetoothDevice 생성
fun createMockBluetoothDevice(address: String, name: String): BluetoothDevice {
val constructor = BluetoothDevice::class.java.getDeclaredConstructor(String::class.java)
constructor.isAccessible = true
val device = constructor.newInstance(address)
val nameField = BluetoothDevice::class.java.getDeclaredField("mName")
nameField.isAccessible = true
nameField.set(device, name)
return device
}
// Mock ScanRecord 생성
fun createMockScanRecord(): ScanRecord? {
return try {
val constructor: Constructor<ScanRecord> = ScanRecord::class.java.getDeclaredConstructor(
ByteArray::class.java, // 광고 데이터
ByteArray::class.java, // 스캔 응답 데이터
List::class.java, // 서비스 UUIDs
Int::class.javaPrimitiveType, // 광고 플래그
Int::class.javaPrimitiveType, // TxPowerLevel
String::class.java, // Device Name
Int::class.javaPrimitiveType // Manufacturer Specific Data
)
constructor.isAccessible = true
constructor.newInstance(
byteArrayOf(0x02, 0x01, 0x06), // 광고 데이터
byteArrayOf(0x09, 0x09, 0x4D, 0x6F, 0x63, 0x6B, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65), // 스캔 응답 데이터
listOf(), // 서비스 UUIDs
-1, // 광고 플래그
0, // TxPowerLevel
"Mock Device", // Device Name
0 // Manufacturer Specific Data
)
} catch (e: Exception) {
e.printStackTrace()
null
}
}
// Mock ScanResult 생성
fun createMockScanResult(): ScanResult {
val mockDevice = createMockBluetoothDevice("00:11:22:33:44:55", "Mock Device")
val mockScanRecord = createMockScanRecord()
return ScanResult(mockDevice, mockScanRecord, 0, System.nanoTime())
}
2. ScanCallback 설정
이제 ScanCallback을 설정하고, Mock 데이터를 사용하여 콜백을 호출합니다.
Kotlin
val mockScanResult = createMockScanResult()
val scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
super.onScanResult(callbackType, mockScanResult)
// 결과 처리
}
override fun onBatchScanResults(results: List<ScanResult>) {
super.onBatchScanResults(listOf(mockScanResult))
// 결과 처리
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
// 오류 처리
}
}
// 디버그 모드에서 Mock 데이터로 콜백 호출
scanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, mockScanResult)
이 코드를 사용하면 디버그 모드에서 no.nordicsemi.android.support.v18.scanner.ScanCallback을 가짜로 만들어 테스트할 수 있습니다. 이를 통해 실제 장치 없이도 Bluetooth 기능을 테스트하고 디버깅할 수 있습니다.
이 블로그 게시물이 도움이 되길 바랍니다! 추가로 궁금한 점이 있으면 언제든지 물어보세요. 😊
...
하지만 실제 코딩에서는 진척이 없습니다. 읽어 주셔서 감사합니다.
오늘의 이야기
#스하리1000명프로젝트,
한국에서 길을 잃었나요? 한국어를 못하더라도 이 앱을 사용하면 쉽게 돌아다닐 수 있습니다.
귀하의 언어로 말하면 귀하의 언어로 번역, 검색 및 결과가 표시됩니다.
여행자에게 좋습니다! 영어, 일본어, 중국어, 베트남어 등 10개 이상의 언어를 지원합니다.
지금 사용해 보세요!
https://play.google.com/store/apps/details?id=com.billcoreatech.opdgang1127
오늘의 이야기
#스치니1000프로젝트 #재미 #행운기원 #Compose #Firebase
🎯 야 너 토요일마다 로또 확인하냐?
나도 맨날 “혹시나~” 하면서 봤거든 ㅋㅋ
근데 이제는 그냥 안 해
AI한테 맡겼어 🤖✨
그것도 구글 Gemini로다가!
그래서 앱 하나 만들었지
👉 “로또 예상번호 by Gemini” 🎱
AI가 분석해서 번호 딱! 뽑아줌
그냥 보고 참고만 하면 됨
재미로 해도 좋고…
혹시 모르는 거잖아? 😏
https://play.google.com/store/apps/details?id=com.billcorea.gptlotto1127
2026/04/11
오늘의 이야기
JavaScript로 페이지 요소 값 가져오기 및 세션을 통한 값 전달
페이지 최상단의 특정 항목 값 알아내기
JavaScript를 사용하여 페이지 최상단에 있는 특정 항목의 값을 알아내는 방법은 매우 간단합니다. document.getElementById 또는 document.querySelector를 사용하여 특정 요소를 선택하고, 해당 요소의 값을 가져올 수 있습니다.
예제 코드:
HTML
<!DOCTYPE html>
<html>
<head>
<title>Get Element Value</title>
</head>
<body>
<div id="topElement">This is the top element</div>
<script>
// 특정 ID를 가진 요소 선택
const topElement = document.getElementById('topElement');
// 요소의 텍스트 내용 가져오기
const elementValue = topElement.innerText;
console.log(elementValue); // "This is the top element" 출력
</script>
</body>
</html>
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
위 예제에서는 id가 topElement인 요소를 선택하고, 해당 요소의 텍스트 내용을 innerText 속성을 사용하여 가져옵니다.
또 다른 방법으로는 document.querySelector를 사용할 수도 있습니다:
HTML
<!DOCTYPE html>
<html>
<head>
<title>Get Element Value</title>
</head>
<body>
<div class="top-element">This is the top element</div>
<script>
// 특정 클래스를 가진 요소 선택
const topElement = document.querySelector('.top-element');
// 요소의 텍스트 내용 가져오기
const elementValue = topElement.innerText;
console.log(elementValue); // "This is the top element" 출력
</script>
</body>
</html>
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
이 방법은 CSS 선택자를 사용하여 요소를 선택할 수 있어 더욱 유연합니다.
세션을 통해 하위 페이지로 값 전달하기
세션을 통해 하위 페이지로 값을 전달하는 방법은 여러 가지가 있습니다. 여기서는 JavaScript와 HTML을 사용하여 세션 스토리지를 활용하는 방법을 설명하겠습니다.
1. 값 저장하기 (상위 페이지)
먼저, 상위 페이지에서 세션 스토리지에 값을 저장합니다.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Save to Session Storage</title>
</head>
<body>
<input type="text" id="inputValue" placeholder="Enter some value">
<button onclick="saveToSession()">Save</button>
<script>
function saveToSession() {
const inputValue = document.getElementById('inputValue').value;
sessionStorage.setItem('savedValue', inputValue);
alert('Value saved to session storage!');
}
</script>
</body>
</html>
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
2. 값 가져오기 (하위 페이지)
하위 페이지에서 세션 스토리지에 저장된 값을 가져옵니다.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Retrieve from Session Storage</title>
</head>
<body>
<div id="displayValue"></div>
<script>
window.onload = function() {
const savedValue = sessionStorage.getItem('savedValue');
document.getElementById('displayValue').innerText = savedValue ? savedValue : 'No value found in session storage.';
}
</script>
</body>
</html>
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
이 예제에서는 상위 페이지에서 입력된 값을 세션 스토리지에 저장하고, 하위 페이지에서 해당 값을 가져와서 표시합니다.
JavaScript로 7일 전 날짜 구하기
JavaScript를 사용하여 7일 전의 날짜를 구하는 방법은 매우 간단합니다. Date 객체와 setDate 메서드를 사용하면 됩니다.
예제 코드:
JavaScript
// 현재 날짜 가져오기
let currentDate = new Date();
// 7일 전 날짜 계산
currentDate.setDate(currentDate.getDate() - 7);
// 결과 출력
console.log(currentDate);
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
이 코드는 현재 날짜에서 7일을 빼서 7일 전의 날짜를 계산합니다.
이 블로그 게시글이 도움이 되셨길 바랍니다! 추가적인 질문이 있거나 다른 도움이 필요하시면 언제든지 말씀해 주세요. 😊
오늘의 이야기
클라우드 기능 활용한 이메일 발송법, 파이어스토어&파이어베이스-메일 발송
• 이 블로그 게시물은 클라우드 기술을 사용하여 이메일을 더 쉽게 보낼 수 있는 방법을 설명합니다. 특히 신규 가입자에게 환영 이메일을 보내거나 사용자 지원 요청을 처리하는 시나리오에서 그렇습니다.
• 이메일 전송을 자동화하고 애플리케이션 내 사용자 지원 기능을 향상시키기 위해 클라우드 기능을 사용하는 이점을 강조합니다.
• 게시물은 파이어베이스 프로젝트 설정, 파이어베이스 CLI 설치, 파이어스토어 트리거 이메일 확장 설치 등에 대한 단계별 안내를 제공한다.
• SMTP 연결 URI, Firebase 수집명, 주소에서 기본 설정, SMTP 비밀번호 등 확장에 필요한 필수 구성도 포함합니다.
• 또한 게시물은 연락처 요청을 제출하라는 클라이언트 요청에 의해 트리거된 클라우드 기능에 대한 코드 스니펫을 포함하여 이메일을 보내기 위해 화재 기반 전송 이메일 확장을 활용하는 호출 가능한 클라우드 기능을 작성하는 방법을 보여준다.
• 클라우드 기능이 확장자에 의해 모니터링되는 Firestore 수집 지원_요청에 문서를 추가하여 문서의 내용을 기반으로 이메일 전송을 트리거하는 방법을 설명합니다.
https://blog.canopas.com/how-to-send-emails-using-cloud-functions-firestore-firebase-send-email-ff4702a16fef
How To Send Emails Using Cloud Functions, Firestore & Firebase-Send-Email
A Guide to Cloud Functions, Firestore, and Firebase-Send-Email
blog.canopas.com
오늘의 이야기
뷰모델로 안드로이드 오토에서 코드 재사용
• 이 기사는 구성 변경 및 사망 시에도 생존하는 핵심 제트팩 라이브러리인 ViewModels를 사용하여 Android Auto에서 코드를 재사용하는 방법을 탐구합니다.
• 뷰모델은 안드로이드 오토 및 카 앱 라이브러리에서 사용할 수 있어 개발자가 MVVM 패턴을 유지하고 안드로이드 오토의 일반 앱에서 기능을 재사용할 수 있다.
• 안드로이드 오토는 CarService, Session 및 Screen을 포함하는 특정 설정을 가지고 있으며 화면은 수명 주기를 인식하지만 ViewModelStoreOwner가 아닙니다.
• 이를 해결하기 위해 저자는 화면용 ViewModelStoreOwner를 만들고 수명 주기가 파괴된 상태에 도달하면 이를 제거하여 적절한 ViewModel 관리를 보장합니다.
• 저자는 의존성 주입을 위해 Koin을 사용하여 ViewModel을 주입하는 방법을 보여주므로 루트 Koin 범위에서 ViewModel을 쉽게 검색할 수 있습니다.
• 기사는 뷰모델에서 데이터가 변경될 때마다 화면을 무효화하는 것의 중요성을 강조하여 화면이 그에 따라 업데이트되도록 보장합니다.
https://proandroiddev.com/android-auto-and-viewmodel-reuse-your-code-in-your-car-f883437b7ea3
Android Auto and ViewModel: Reuse your code in your car!
See how we can leverage ViewModelStoreOwner and Koin to use ViewModels in Android Auto.
proandroiddev.com
오늘의 이야기
Visual SVN에서 변경 이력 및 내역 확인하기 svn 동기화 CMD 창에서 변경 이력 확인 Visual SVN의 변경 이력을 CMD 창에서 확인하려면 svn log 명령어를 사용합니다. 예를 ...
-
이전 글에서 정리할 것처럼 java에서 kotlin으로 이전을 했습니다. 그러고 나서 보기 시작했는 데, DefaultSharedPrefernces의 사용할 수 없는 환경으로 변경이 된 것을 알게 되었습니다. 이전 prefs = Prefere...