DB
PHP
LLM

S&P 500

SPI@SPX 미국 2026.02.13 16:49 현지시간 기준 |10분 지연제공

6,836.17

전일대비 3.41 (+ 0.05% )

나스닥 종합

NAS@IXIC 미국 2026.02.13 16:15 현지시간 기준 |15분 지연제공

22,546.67

전일대비 50.48 ( -0.22% )

다우 산업

DJI@DJI 미국 2026.02.13 16:20 현지시간 기준 |15분 지연제공

49,500.93

전일대비 48.95 (+ 0.10% )

쿼리 실행 절차 :: MariaDB

작성자아이디 : skok1025, 2022-09-23 17:02:48
카테고리 : DB MariaDB 게시글 수정

단계 1) 사용자로부터 요청된 SQL 문장을 잘게 쪼개서 MariaDB 서버가 이해할 수 있는 수준으로 분리 (파스 트리) 한다. - SQL 파싱 (Parsing)

단계 2) SQL 의 파싱 정보 (파싱트리) 를 확인하면서, 어떤 테이블부터 읽고 어떤 인덱스를 읽을지 선택한다. - 옵티마이져

  • 불필요한 조건의 제거 및 복잡한 연산의 단순화

  • 여러 테이블의 조인이 있는 경우 어떤 순서로 테이블을 읽을지 결정

  • 각 테이블에 사용된 조건과 인덱스의 통계 정보를 이용해 사용할 인덱스를 결정

  • 가져온 레코드들을 임시 테이블에 넣고 다시 한번 가공해야 하는지 결정

단계 3) 두번째 단계에서 결정된 테이블의 읽기 순서나 선택된 인덱스를 이용해 스토리지 엔진으로부터 데이터를 가져온다.

  • 수립된 실행 계획대로 스토리지 엔진에 레코드를 읽어오도록 요청하고 MariaDB 엔진에서는 스토리지 엔진으로부터 받은 레코드를 조인하거나 정렬하는 작업진행.

세션(Session) 핸들러::PHP

작성자아이디 : skok1025, 2022-09-19 21:41:24
카테고리 : Language PHP 게시글 수정

데이터베이스를 이용한 session 처리 핸들러 예제입니다. (* SessionHandlerInterface 인터페이스 구현체,)

아래와 같이 open, close, read, write. destroy, gc 를 구현하면 DB 를 통해서도 세션관리가 가능합니다.

(일반적으로는 프레임워크에서 세션처리 구현이 되어있기 때문에 아래와 같이 작업할 일이 없음)


테이블

    CREATE TABLE sessions(
        id VARCHAR(255) UNIQUE NOT NULL,
        payload TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        update_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    )



소스

<?php

date_default_timezone_set('Asia/Seoul');

/**
* Session Handler Interface
*/
class DatabaseSessionHandler implements SessionHandlerInterface
{
private PDO $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}

public function open($path, $name)
{
return true;
}

public function read($id)
{
$sth = $this->pdo->prepare('SELECT * FROM sessions WHERE `id` = :id');

if ($sth->execute([':id' => $id])) {
if ($sth->rowCount()>0) {
$payload = $sth->fetchObject()->payload();
} else {
$sth = $this->pdo->prepare('INSERT INTO sessions(`id`) VALUES(:id)');
$sth->execute([':id' => $id]);
}
}

return $payload ?? '';
}

public function close()
{
return true;
}

public function destroy($id)
{
$this->pdo
->prepare('DELETE FROM sessions WHERE `id` = :id')
->execute([':id' => $id])
;
}

public function gc($max_lifetime)
{
$sth = $this->pdo->prepare('SELECT * FROM sessions');

if ($sth->execute()) {
while ($row = $sth->fetchObject()) {
$timestamp = strtotime($row->created_at);

if (time() - $timestamp > $max_lifetime) {
$this->destroy($row->id);
}
}
return true;
}

return false;
}

public function write($id, $data)
{
return $this->
pdo->prepare('UPDATE sessions SET `payload` = :payload WHERE `id` = :id')
->execute([':payload' => $data, ':id' =>$id]);
}
}

// 세션 핸들러 등록
session_set_save_handler(new DatabaseSessionHandler(new PDO('mysql:dbname=test;host=127.0.0.1;', 'root', 'root')));
session_start();
$_SESSION['message'] = 'Hello world';
$_SESSION['foo'] = new stdClass();

session_gc(); // 세션 정리

리플렉션 (ReflectionClass) :: PHP

작성자아이디 : skok1025, 2022-09-19 21:25:23
카테고리 : Language PHP 게시글 수정

리플렉션을 통해 객체의 메타데이터 (properties, class) 를 확인이 가능하다.



/**
* ReflectionClass
*/

class A
{
private $message = "Hello world";

public function __construct($message)
{
$this->message = $message;
}
}

class B extends A
{

}
// 특정 클래스 "A" 에 대하여 private 의 properties 가져오기
$refClass = new ReflectionClass('\A');
var_dump($refClass->getProperties(ReflectionProperty::IS_PRIVATE));
==>
array(1) { [0]=> object(ReflectionProperty)#2 (2) { ["name"]=> string(7) "message" ["class"]=> string(1) "A" } } 

// B 클래스가 A 클래스의 자식클래스인지 확인 
$refClassB = new ReflectionClass('\B');
var_dump($refClassB->isSubclassOf('\A'));
==> bool(true)
// "message" 이름의 property 정보
$messageProperty = $refClass->getProperty('message');
var_dump($messageProperty);
=> 
object(ReflectionProperty)#3 (2) { ["name"]=> string(7) "message" ["class"]=> string(1) "A" }

Converter 활용

작성자아이디 : skok1025, 2022-08-29 19:34:40
카테고리 : Language Java 게시글 수정

Java 에는 Converter 라는 인터페이스가 있다.  해당 인터페이스는 A 타입 -> B 타입으로 변경을 할 때 사용한다. (ex. String -> Integer)

소스로 예를 들자면 "127.0.0.1:8080" 형태의 String 을 DTO 객체로 변환을 아래와 같이 처리가 가능하다. 

1) IpPort DTO 

import lombok.EqualsAndHashCode;
import lombok.Getter;

@Getter
@EqualsAndHashCode
public class IpPort {
private String ip;
private int port;

public IpPort(String ip, int port) {
this.ip = ip;
this.port = port;
}
}
2) String -> IpPort DTO Converter
import hello.typeconverter.type.IpPort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;

@Slf4j
public class StringToIpPortConverter implements Converter<String, IpPort> {
@Override
public IpPort convert(String source) {
log.info("convert source={}", source);
// 127.0.0.1:8080

String[] split = source.split(":");

String ip = split[0];
int port = Integer.parseInt(split[1]);

return new IpPort(ip, port);
}
}
3) 사용
@Test
void StringToIpPort() {
StringToIpPortConverter converter = new StringToIpPortConverter();
String source = "127.0.0.1:8080";

IpPort result = converter.convert(source);

assertThat(result).isEqualTo(new IpPort("127.0.0.1", 8080));
}

[Postgresql] vacuum

작성자아이디 : skok1025, 2022-07-26 18:09:08
카테고리 : DB Postgresql 게시글 수정

간략요약하자면 

UPDATE, DELETE 를 한다고 해서 Postgresql 은 물리적인 공간이 사라지는 것은 아니다. (Live Tuple -> Dead Tuple 이 되는 것임)

따라서 물리적인 공간을 지우기 위해서는 "vacuum" 이라는 것을 제공한다. 

- auto vacuum : https://nrise.github.io/posts/postgresql-autovacuum/ 참조

- alter table vauum (* 컬럼타입을 변경하는 것만으로도 full vacuum 과 동일한 효과)

           BEGIN;
                LOCK TABLE {테이블명} IN ACCESS EXCLUSIVE MODE;
                ALTER TABLE {테이블명} ADD COLUMN _tmp INTEGER NULL;
                ALTER TABLE {테이블명} ALTER COLUMN _tmp TYPE TEXT;
                ALTER TABLE {테이블명} DROP COLUMN _tmp;
            END;