2024년 11월 9일 토요일

Flutter #1

 [Flutter 교육]


Dart2JS

YAML
복사
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 js: ^0.7.1 json_annotation: ^4.9.0 freezed_annotation: ^2.4.4 dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^3.0.0 build_runner: ^2.4.11 freezed: ^2.5.2 json_serializable: ^6.8.0

1. 모델 정의 (user_model.dart)

Dart
복사
import 'package:freezed_annotation/freezed_annotation.dart'; part 'user_model.g.dart'; part 'user_model.freezed.dart'; class User with _$User { const factory User({ required String id, required String name, required int age, String? email, ([]) List<String> roles, }) = _User; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); }

해설

@freezed: 불변 객체를 생성하는 어노테이션
_$User: Freezed가 생성하는 믹스인
const factory: 불변 인스턴스 생성을 위한 팩토리 생성자
@Default([]): 기본값 지정
fromJson: JSON 변환을 위한 팩토리 메서드

2. JavaScript 서비스 정의

Dart
복사
('UserService') class UserService { external UserService(); external JSPromise getUserById(String id); external JSPromise updateUser(JSObject user); external JSPromise searchUsers(JSObject criteria); }

해설

@JS(): JavaScript 클래스/함수와 매핑
external: 실제 구현은 JavaScript에 있음을 표시
JSPromise: JavaScript Promise를 나타내는 타입
JSObject: JavaScript 객체를 나타내는 타입

3. 리포지토리 구현

Dart
복사
class UserRepository { final UserService _service = UserService(); Future<User> getUserById(String id) async { try { final JSObject result = await promiseToFuture(_service.getUserById(id)); return User.fromJson(result.dartify() as Map<String, dynamic>); } catch (e) { throw Exception('Failed to fetch user: $e'); } }

해설

promiseToFuture: JS Promise를 Dart Future로 변환
dartify(): JS 객체를 Dart 객체로 변환
as Map<String, dynamic>: 타입 안전성을 위한 캐스팅
에러 처리와 예외 전파

4. 데이터 변환 프로세스

Dart
복사
// JS → Dart final JSObject result = await promiseToFuture(_service.getUserById(id)); return User.fromJson(result.dartify() as Map<String, dynamic>); // Dart → JS final jsUser = user.toJson().jsify();

변환 과정

JavaScript → Dart:
Plain Text
복사
JS Object → JSObject → Dart Map → User 객체
Dart → JavaScript:
Plain Text
복사
User 객체 → Dart Map → JSObject → JS Object

5. 위젯 구현의 주요 포인트

Dart
복사
class _UserManagementWidgetState extends State<UserManagementWidget> { Future<void> _updateUserAge() async { if (_selectedUser == null) return; try { final updatedUser = await _repository.updateUser( _selectedUser!.copyWith(age: _selectedUser!.age + 1) ); setState(() => _selectedUser = updatedUser); } catch (e) { // 에러 처리 } }

해설

copyWith: Freezed가 제공하는 불변 업데이트 메서드
상태 관리: setState를 통한 UI 업데이트
비동기 작업 처리
에러 처리와 사용자 피드백

6. JavaScript 구현

JavaScript
복사
class UserService { async getUserById(id) { const mockUser = { id: id, name: 'John Doe', age: 30, email: 'john@example.com', roles: ['user', 'admin'] }; return mockUser; }

해설

비동기 메서드 (async/await 사용)
Promise 반환
모의 데이터 제공
Dart 모델과 일치하는 데이터 구조

7. 주요 기술적 고려사항

타입 안전성

Dart
복사
// 잘못된 방법 final result = await _service.getUserById(id); // 타입 불안전 // 올바른 방법 final JSObject result = await promiseToFuture(_service.getUserById(id));

메모리 관리

Dart
복사
// 메모리 누수 가능성 element.addEventListener('click', allowInterop(handleClick)); // 올바른 방법 final handler = allowInterop(handleClick); element.addEventListener('click', handler); element.removeEventListener('click', handler);

성능 최적화

Dart
복사
// 비효율적 for (var user in users) { final jsUser = user.toJson().jsify(); // 매번 변환 } // 최적화 final jsUsers = users.map((u) => u.toJson()).toList().jsify(); // 한 번에 변환

8. 베스트 프랙티스

에러 처리
Dart
복사
try { final result = await promiseToFuture(_service.riskyOperation()); } catch (e) { if (e is JSError) { // JavaScript 에러 처리 } else { // Dart 에러 처리 } }
타입 체크
Dart
복사
if (result is! JSObject) { throw TypeError('Expected JSObject'); }
널 체크
Dart
복사
final email = user.email; // Freezed가 제공하는 널 안전성 if (email != null) { // 안전한 처리 }

9. 디버깅 팁

콘솔 로깅
Dart
복사
('console') external void log(dynamic message); // 사용 log(user.toJson()); // JavaScript 콘솔에서 확인
개발자 도구 활용
Dart
복사
// 브레이크포인트 설정 가능한 코드 구조 Future<User> getUserById(String id) async { final result = await promiseToFuture(_service.getUserById(id)); final json = result.dartify(); // 여기서 중단점 설정 return User.fromJson(json); }


출처 : https://cheddar-sparrow-aba.notion.site/Dart2JS-13997e0a8ff3807da3c6d76e0011bd4d



2024년 6월 29일 토요일

ORACLE DB - INDEX

 
/***********************************************
  Oracle DB 인덱스 생성
   Oracle 19c 기준으로 작성되었습니다. 
***********************************************/



/***********************************************
 CUST, CUST_DTL 테이블, 인덱스 상태 조회
   STR 계정 접속
***********************************************/
SELECT
    OBJECT_TYPE,
    OBJECT_NAME,
    CREATED
FROM USER_OBJECTS
ORDER BY 2,1;



/***********************************************
 통계 정보 생성
   STR 계정 접속
***********************************************/
SELECT
    TABLE_NAME,
    TABLESPACE_NAME,
    LAST_ANALYZED
FROM USER_TABLES
ORDER BY 1;
-- 통계 정보 생성
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'STR', TABNAME=>'CUST');
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'STR', TABNAME=>'CUST_DTL');
-- 통계 정보 삭제
EXEC DBMS_STATS.DELETE_TABLE_STATS(OWNNAME=>'STR', TABNAME=>'CUST');
EXEC DBMS_STATS.DELETE_TABLE_STATS(OWNNAME=>'STR', TABNAME=>'CUST_DTL');



/***********************************************
 인덱스 추가 생성
  테이블명: CUST 
  인덱스명: CUST_X1(CUST_NM)
   STR 계정 접속
***********************************************/

SELECT *
FROM STR.CUST
WHERE CUST_NO = '20221125TKDN00000007';

-- CUST_NM 조회
-- 김영칠 3건, 김일영 2건, 김일삼 1건
SELECT *
FROM STR.CUST
WHERE CUST_NM = '김영칠';

CREATE INDEX STR.CUST_X1 ON STR.CUST
(CUST_NM)
TABLESPACE TS_STR_I;


SELECT
    TABLE_NAME,
    INDEX_NAME,
    COLUMN_NAME,
    COLUMN_POSITION
FROM USER_IND_COLUMNS
ORDER BY 1, 2;


/***********************************************
 FBI 인덱스 추가 생성
  테이블명: CUST 
  인덱스명: CUST_X1(CUST_NM)
   STR 계정 접속
***********************************************/
SELECT * 
FROM STR.CUST_DTL
WHERE MBL_NO = '015-0101-0101';
SELECT * 
FROM STR.CUST_DTL
WHERE MBL_NO = '01501010101';
SELECT
  MBL_NO,
  REPLACE(MBL_NO,'-','')
FROM STR.CUST_DTL;
SELECT * 
FROM STR.CUST_DTL
WHERE REPLACE(MBL_NO,'-','') = '01501010101';

CREATE INDEX STR.CUST_DTL_X1 ON STR.CUST_DTL
(REPLACE(MBL_NO,'-',''))
TABLESPACE TS_STR_I;
SELECT
    A.TABLE_NAME,
    A.INDEX_NAME,
    B.INDEX_TYPE,
    A.COLUMN_NAME,
    A.COLUMN_POSITION
FROM 
    USER_IND_COLUMNS A,
    USER_INDEXES B
WHERE A.TABLE_NAME = B.TABLE_NAME 
AND A.INDEX_NAME = B.INDEX_NAME
ORDER BY 1, 2;



-- 인덱스 삭제
DROP INDEX STR.CUST_X1;
DROP INDEX STR.CUST_DTL_X1;


[출처] DB보다


ORACLE DB - TABLESPACE, 계정


/***********************************************
  Oracle DB 계정 생성
  Oracle 19c 기준으로 작성되었습니다. 
***********************************************/

/***********************************************
  DB계정 상태 확인
***********************************************/
--DB계정 상태 확인
SELECT
    USERNAME,
    PROFILE,
    ACCOUNT_STATUS,
    DEFAULT_TABLESPACE,
    TEMPORARY_TABLESPACE,
    CREATED,
    EXPIRY_DATE
FROM DBA_USERS;


/***********************************************
  Tablespace 상태 확인
***********************************************/
-- Tablespace 상태 확인
SELECT 
    TABLESPACE_NAME, 
    FILE_NAME, 
    BYTES/1024/1024 AS "SIZE_MB"
FROM DBA_DATA_FILES;


/***********************************************
  Tablespace 생성
    데이터파일 위치 확인: /oracle/app/oracle/oradata/STR/
***********************************************/
-- 테이블 영역
CREATE TABLESPACE TS_STR_D
DATAFILE '/oracle/app/oracle/oradata/STR/TS_STR_D_001.DBF' SIZE 2048M;
-- 인덱스 영역
CREATE TABLESPACE TS_STR_I
DATAFILE '/oracle/app/oracle/oradata/STR/TS_STR_I_001.DBF' SIZE 2048M;


/***********************************************
  STR DB 계정 생성
***********************************************/
-- STR DB계정 생성
CREATE USER STR
IDENTIFIED BY "oracle"
DEFAULT TABLESPACE TS_STR_D
ACCOUNT UNLOCK;
-- STR DB계정 권한 생성
GRANT CONNECT, RESOURCE TO STR;


/***********************************************
  STR DB 계정 프로파일 변경
***********************************************/
-- DEFAULT 프로파일 상태 확인
SELECT 
    * 
FROM DBA_PROFILES
WHERE PROFILE = 'DEFAULT';

FAILED_LOGIN_ATTEMPTS        비밀번호 실패 허용 수
PASSWORD_LIFE_TIME             비밀번호 유효 기간  
PASSWORD_LOCK_TIME           비밀번호  잠김 시간
PASSWORD_GRACE_TIME        비밀번호 변경 메세지 출력 일자

-- PROFILE 설정 변경
ALTER PROFILE DEFAULT
LIMIT
FAILED_LOGIN_ATTEMPTS   UNLIMITED
PASSWORD_LIFE_TIME        UNLIMITED
PASSWORD_LOCK_TIME      UNLIMITED
PASSWORD_GRACE_TIME   UNLIMITED
;

-- PROFILE 설정 원복
ALTER PROFILE DEFAULT
LIMIT
FAILED_LOGIN_ATTEMPTS 10
PASSWORD_LIFE_TIME    180
PASSWORD_LOCK_TIME    1
PASSWORD_GRACE_TIME   7
;


/***********************************************
  STR DB 계정 삭제 및 테이블스페이스 삭제
***********************************************/
-- DB계정 삭제
DROP USER STR CASCADE;

-- 테이블스페이스 삭제
DROP TABLESPACE TS_STR_D INCLUDING CONTENTS AND DATAFILES;
DROP TABLESPACE TS_STR_I INCLUDING CONTENTS AND DATAFILES;
 

[출처] DB보다


2024년 6월 28일 금요일

ORACLE DB - SEQUENCE


/***********************************************

Oracle DB 계정 생성

Oracle 19c 기준으로 작성되었습니다.
***********************************************/

/********************************************************
시퀀스 생성
시퀀스명: SEQ_TEST_1
STR 계정 접속
********************************************************/

-- 시퀀스 생성
CREATE SEQUENCE STR.SEQ_TEST_1
MINVALUE 1
MAXVALUE 999999999
INCREMENT BY 1
START WITH 1
CACHE 20
ORDER
CYCLE;

-- 시퀀스 상태
SELECT
SEQUENCE_NAME,
LAST_NUMBER,
MIN_VALUE,
MAX_VALUE,
LENGTH(MAX_VALUE) AS "LENGTH",
INCREMENT_BY,
CYCLE_FLAG,
ORDER_FLAG,
CACHE_SIZE
FROM USER_SEQUENCES
WHERE SEQUENCE_NAME = 'SEQ_TEST_1';


/********************************************************
시퀀스 사용 방법
STR 계정 접속
********************************************************/

-- 시퀀스 다음 값 생성
SELECT STR.SEQ_TEST_1.NEXTVAL FROM DUAL;

-- 시퀀스 현재 상태 값
SELECT STR.SEQ_TEST_1.CURRVAL FROM DUAL;

-- 시퀀스 증가 번호 변경
ALTER SEQUENCE STR.SEQ_TEST_1 INCREMENT BY 1;

-- 시퀀스 시작 번호 변경
ALTER SEQUENCE STR.SEQ_TEST_1 RESTART START WITH 1;


/********************************************************
시퀀스 꿀팁
STR 계정 접속
********************************************************/

SELECT STR.SEQ_TEST_1.NEXTVAL FROM DUAL;

SELECT TO_CHAR(STR.SEQ_TEST_1.NEXTVAL,'FM000000000') FROM DUAL;

SELECT
TO_CHAR(SYSDATE, 'YYYYMMDD') ||
TO_CHAR(STR.SEQ_TEST_1.NEXTVAL, 'FM000000000')
FROM DUAL;


/********************************************************
테이블 생성(시퀀스 사용을 위한 테이블 생성)
STR 계정 접속
********************************************************/

-- 테이블 생성
CREATE TABLE STR.TEST
(
TEST_NO VARCHAR2(20)
)
TABLESPACE TS_STR_D;

-- 10건 데이터 입력
INSERT INTO STR.TEST
SELECT
TO_CHAR(SYSDATE, 'YYYYMMDD') ||
TO_CHAR(STR.SEQ_TEST_1.NEXTVAL, 'FM000000000') "TEST_NO"
FROM DUAL
CONNECT BY LEVEL <= 10;

COMMIT;

-- 데이터 조회
SELECT * FROM STR.TEST;

-- 시퀀스 현재 상태 값
SELECT STR.SEQ_TEST_1.CURRVAL FROM DUAL;

-- 시퀀스 증가 번호 변경
ALTER SEQUENCE STR.SEQ_TEST_1 INCREMENT BY 1;



/********************************************************
고객 번호 시퀀스 생성 예제
시퀀스명: SEQ_CUST_1
STR 계정 접속
********************************************************/

-- 시퀀스 생성
CREATE SEQUENCE STR.SEQ_CUST_1
MINVALUE 1
MAXVALUE 99999999
INCREMENT BY 1
START WITH 1
CACHE 20
ORDER
CYCLE;

-- 고객 번호 생성
SELECT
TO_CHAR(SYSDATE,'YYYYMMDD') ||
DBMS_RANDOM.STRING('U',4) ||
TO_CHAR(STR.SEQ_CUST_1.NEXTVAL,'FM00000000') AS "CUST_NO"
FROM DUAL
CONNECT BY LEVEL <= 5;

-- 오브젝트 삭제
SELECT
'DROP '||OBJECT_TYPE||' STR.'||OBJECT_NAME||';'
FROM USER_OBJECTS
WHERE OBJECT_NAME IN ('SEQ_CUST_1','SEQ_TEST_1','TEST');

[출처] DB보다


MSSQL - Cursor vs Temp Table

#테이블 변수사용의 예 use pubs go declare @tmptable table (     nid int identity(1,1) not null,     title varchar (80) not null ) -- 테이블 변수 선언 inse...