1. 백엔드 Cache 적용하기 => 보통 redis나 memCached 를 많이 이용하지만, 당연히 mongoDB casandra등 다른 방법을 이용할 수 있다

    - 이를 통해 DB query를 하지않고 바로 리턴하게 된다. 가끔씩 db를 조회해서 최신정보를 가져오는 step은 readThrough라고 부름.   
2.  (SQL구조 개선) query tunning + index추가 작업 .

                          (+N+1 Query 문제 해결. -> 게시글하나+댓글N개인 경우  N+1조회 등)

 

3. 데이타가 클때 : Payload Compresion 적용. (예: brotli 솔루션)

 

4. 프론트 엔드 개선:  데이터 많은 곳에 paging 적용 등 UI 개선을

                                프론트에서 Cache 적용하기 (react-cache 등 적용해서 API호출 회수 자체를 감소 가능) 

 

5.    비동기 logging :  로그 때문에 시스템이 느려질 수도 있으므로 loggiin에 비동기 방식 적용. 

        및  Connection Pool 을 유지/관리 (계속 새로 오픈하는 것 보다 속도가 좋으므로)

    

    

Posted by yongary
,

oracle DDL 예제

mongoDB, redis 2023. 8. 4. 10:31

*TABLESPACE 생성

CREATE TABLESPACE TS_BIZHOME
DATAFILE '저장위치' SIZE 500M
AUTOEXTEND ON NEXT 100M;
저장위치: '/app/ora19c/oradata/ORCL/ts_bizhome01.dbf'   ora19c와 ORCL은 변경가능성있음.유저생성, 테이블스페이스 권한 주기:
create user [id] identified by [pw] default tablespace 테이블스페이스명;
grant connect, resource (,dba) to [id];
(alter user [유저명] default tablespace [테이블스페이스이름] quota unlimited on users;)
commit;
참고 View:  GRANT CREATE VIEW TO userId; 

 

* DDL 예제. (TB_C_GRPCODE, TB_C_DTLCODE)
CREATE TABLE TB_C_DTLCODE
(
GRP_CD CHAR(2) NOT NULL ,
DTL_CD VARCHAR2(2) NOT NULL ,
DTL_NM VARCHAR2(30) NOT NULL ,
BIGO VARCHAR2(100) NULL
);
CREATE UNIQUE INDEX TB_C_DTLCODE_PK ON TB_C_DTLCODE
(GRP_CD ASC,DTL_CD ASC);ALTER TABLE TB_C_DTLCODE
ADD CONSTRAINT TB_C_DTLCODE_PK PRIMARY KEY (GRP_CD,DTL_CD);CREATE TABLE TB_C_GRPCODE
(
GRP_CD CHAR(2) NOT NULL ,
GRP_NM VARCHAR2(30) NOT NULL
);CREATE UNIQUE INDEX TB_C_GRPCODE_PK ON TB_C_GRPCODE
(GRP_CD ASC);ALTER TABLE TB_C_GRPCODE
ADD CONSTRAINT TB_C_GRPCODE_PK PRIMARY KEY (GRP_CD);ALTER TABLE TB_C_DTLCODE
ADD (CONSTRAINT R_309 FOREIGN KEY (GRP_CD) REFERENCES TB_C_GRPCODE (GRP_CD));

Posted by yongary
,

시스템 디자인 + MSA

BACK-END 2023. 7. 28. 13:07

1. 요구사항 명확화 : 핵심기능 , 트래픽이나 유저수 등 확인.  (1초에 1000요청, 유저 100만명에 서버 기본2대+1씩,  1명당 하루 86.4건 요청)


(High Level Design)

2.1 API - High Level Design (Rest API)   

2.2 Component - High Level Design : 로드 밸런스 + VM 몇대(x 오토스케일링) + DB 단
      - 프론트를 SPA방식으로, 웹서버 없이 대신에
          글로벌서비스의 경우 CDN이나,   로컬서비스면 S3같은 object storage로 미디어 부하분리.
      (VM이냐 컨테이너 기반이냐는  조직이 크고 여러 팀으로 나누어 개발한다면 독립배포가 중요해져서 컨테이너 기반이 좋을 것 같고..
                                                      조직이 작으면 VM기반이 좋을 것 같음)                                                 

2.3 DB선택 : 복제냐 샤딩이냐,   A:카산드라/실리아.  B. dynamoDB. C. mongoDB/documentDB. 4. RDB
       => 옵션중에  트래픽이 많거나 많아질 확률이 있고  필드간의 관계도 좀 필요하다면 B/C 중에 선택!
            (전반적으로 B/C가  샤딩등 분산환경에 유리하다. RDB보다는 개발리소스도 좀 적게 들고..)
            B/C의 차이는 C가 좀 더 index등의 튜징여지가 있으므로  엔지니어 구성에 따라 선택가능)
       => 향후 MSA를 대비해 foreign키 없게 하고, Join을 최소화해서 분리가 용이하도록!

 

3. DB 테이블 설계

 

4.(여유가 되면) Fault tolerance 고려

 

DB - 용량에서  1. master/slave구조,  2. 샤딩/ Table파티셔닝  고민필요.      (index 는 application영역이라 보고 일단 제외)
                                                             =>샤드키는 Cardinality가 높은 값으로 선정. 
        ( RDB - postgreSQL만 슈평분할(샤딩과 유사)지원,  mySQL/oracle은 테이블파티셔닝만 지원
          NoSQL - mongoDB, cansandra 등이 샤딩 지원 : 샤딩시 DB가 빨라지지만 aggregation등에선 늦어질 수도 있음)

         master/slave구조:  오라클에선 replication이라고 부르며 transaction replication 방식이 일반적) 

 

 

////// MSA로 전환 전 고려사항//////

1. API Gateway 는 수직 방향    서비스 메시는 수평 방향으로  라우팅/로드밸런싱 등을 수행한다.

2. DB 트랜잭션을 
      A. 동기화 형태로 홀딩하면서 API호출 완료 후 트랜잭션 수행 : 초기에 일반적 방식. 
      B. 분산트랜잭션(즉 2단계 커밋, 표시나 lock을 하고  API호출 후  완료.)으로 할것인지,
      C. 이벤트 기반으로 LLT(long live Transaction)이용하는 사가패턴을 적용하고 실패시 보상트랜잭션을 개발할 건지 고민필요.   

          => 사가패턴도 2가지가 있는데 중앙관리형과  서비스별 자체 관리형이 있다.

 

 

 

//////////// MSA 장단점

MSA의 핵심은  1. 데이터 분리와  2. API Gateway 라고 생각한다.
  (단, 1. 데이터 분리가 난이도가 높기 때문에,
         운영중인 모노리스를 MSA로 변환해야하는 실상황에서는 서비스만 먼저 분리하고 나중에 데이터를 분리하는 방법이 현실적이다) 

 

 

모노리스 장단점:

  • (장점) 배포 및 테스트도 하나의 애플리케이션만 수행하면 되기 때문에
     개발 및 환경설정이 간단, 운영 관리가 용이, 
  • (단점들 : 시스템이 커지기 시작하면 등장)
    - 빌드/테스트 시간이 길어진다.
    작은 수정에도 시스템 전체를 빌드해야 하며, 테스트 시간도 길어진다. 요즘처럼 CI/CD가 강조되는 시점에서는 큰 문제가 될 수 있다.
    - 하나의 서비스가 모든 서비스에 영향을 준다.  이벤트 서비스에 트래픽이 몰려 해당 서버가 죽게 된다면 다른 모든 서비스 역시 마비 되는 상황이 오게 됩니다
    선택적 확장이 불가능
    이벤트로 인해 서비스 접속 량이 폭증할 경우 프로젝트 전체를 확장해야만 한다.

MSA 장단점:  

  • (장점) 1. 서비스별 독립된 배포,  2. 해당 서비스별 확정.   
  • (단점들)
      모노리틱 아키텍처는 서비스간의 호출이 하나의 프로세스 내에서 이루어지기 때문에 속도가 빠르지만, MSA의 경우 서비스간 호출을 API통신을 이용하기 때문에 속도가 느리다.
  • 통신에 사용하기 위해 값을 데이터 모델로 변환시켜주는 오버헤드가 발생 

 

Posted by yongary
,

docker

BACK-END 2023. 7. 11. 09:03

<docker demon 실행>

sudo systemctl start docker (or stop)

sudo systemctl restart docker : 재시작

 

<image들 모두 삭제>

(sudo) docker rmi -f $(docker images -aq)

 

 

<docker 컨테이너 재시작>

sudo docker stop 7e1bc0fdb606

sudo docker start 7e1bc0fdb606

 

 

<docker oracle 11g>

sudo docker run -d -p 1521:1521 jaspeen/oracle-xe-11g

한글설정

docker exec -it <컨테이너 이름> bash

     export NLS_LANG=KOREAN_KOREA.AL32UTF8

 

sqlplus / as sysdba

SELECT * FROM v$nls_parameters WHERE parameter LIKE '%CHARACTERSET';

(결과로 나타나는 NLS_CHARACTERSET 값이 "AL32UTF8"로 표시되어야 합니다.)

그후, 재시작.

docker stop <컨테이너 이름>

docker start <컨테이너 이름>

 

 

<그 외>

$docker pull image명(jenkins, centos등)
$docker images : 이미지 목록조회
  - hub.docker.com 에서 검색 가능
$docker run image명 :이미지 실행.  (--name 컨테이너명 지정가능)
  옵션 -p 내포트:docker포트 -v 내디스크:docker디스크경로(:ro) ro는 ReadOnly     
  옵션 -d (데몬으로 실행)
실행하면서 shell 접속: $docker run -it centos /bin/bash 
$docker exec -it containerName /bin/bash 잘됨(docker run하고난 상태에서 접속)
$docker ps  :컨테이너 조회  (-q 옵션 주면 container ID만 조회됨, -a는 all)
$docker history imageID  :해당 이미지에 관련해 실행된 명령어들
$docker rmi imageID : 이미지 삭제

containerID 관련 명령

$docker rm -f containerID or $(docker ps -aq) : 확실히 죽이는 방법.
$docker top containerID :해당 컨테이너 안에서 top을 돌리는 기능
$docker stop containerID : 해당 컨테이너 중단 (종료시그널로 중단)
$docker kill cotainerID : 완전죽임 (kill시그널로 중단)
$docker rm containerID : 컨테이너를 docker ps 목록에서 삭제, 죽지 않을수도 있음.

Dockerfile

FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY .htpasswd /etc/nginx
COPY default.conf /etc/nginx/conf.d/

$docker build -t mynginx . - 자기만의 이미지 생성

$docker run -p 8500:80 -d mynginx -자기 이미지 실행

Posted by yongary
,

OAuth2 + OpenID

BACK-END 2023. 7. 6. 14:25

OpenID Connect (OIDC)는 OAuth 2.0을 기반으로 한 인증 프로토콜로, JWT (JSON Web Tokens)를 사용하여 사용자 정보를 안전하게 전달합니다. OIDC에서 생성되는 JWT는 특히 'ID 토큰'이라고 불립니다.

ID 토큰에는 아래와 같은 클레임들이 포함될 수 있습니다:

  • iss: 토큰을 발행한 주체(Issuer)를 나타냅니다.
  • sub: 주체(Subject)를 나타냅니다. 이는 고유한 식별자로, 토큰 발행자가 관리하는 사용자의 ID입니다.
  • aud: 수신자(Audience)를 나타냅니다. 이 클레임은 이 토큰이 의도된 수신자 또는 수신자들의 목록입니다.
  • exp: 만료 시간(Expiration Time)을 나타냅니다. 이 시간 이후에는 토큰이 더 이상 유효하지 않습니다.
  • iat: 토큰이 발행된 시간(Issued At Time)을 나타냅니다.

 

FACEBOOK 을 이용한 로그인시. 

  • iss: 이 클레임은 토큰을 발행한 주체(Issuer)를 나타냅니다. 이 경우에는 Facebook이 될 것입니다. 일반적으로, Facebook에서 발행한 토큰의 'iss' 값은 'https://facebook.com'과 같은 형태로 되어있습니다.
  • sub: 이 클레임은 주체(Subject)를 나타냅니다. 이는 토큰 발행자가 관리하는 사용자의 고유 식별자입니다. Facebook을 통해 인증을 받은 경우, 'sub' 클레임은 Facebook에서 사용자에게 할당한 고유 ID입니다.
  • aud: 이 클레임은 수신자(Audience)를 나타냅니다. 이는 해당 토큰이 의도된 수신자입니다. 즉, 특정 e-commerce 서비스의 식별자가 될 것입니다. 이 서비스가 Facebook에 등록되었다면, Facebook은 이 서비스의 'client_id'를 'aud' 클레임에 넣어 ID 토큰을 생성합니다. 그런 다음, 이 토큰이 e-commerce 서비스에 전달되어, 이 서비스는 'aud' 클레임을 검사하여 토큰이 자신에게 보내진 것임을 확인할 수 있습니다.
Posted by yongary
,

Object oriented 디자인 패턴


객체 지향 디자인 패턴(Object-Oriented Design Patterns)은 소프트웨어 개발에서 반복적으로 발생하는 문제들을 해결하기 위해 공통된 설계 방법을 제공하는 패턴들의 집합입니다. 이러한 패턴들은 객체 지향 프로그래밍에서 유용하게 사용될 수 있으며, 코드의 재사용성, 유지보수성, 확장성 등을 향상시킬 수 있습니다. 여기서는 몇 가지 대표적인 객체 지향 디자인 패턴에 대해 설명하겠습니다.

Singleton Pattern (싱글턴 패턴): 이 패턴은 오직 하나의 인스턴스만 생성하고, 그 인스턴스에 접근할 수 있는 전역적인 접근점을 제공합니다. 주로 리소스를 공유하거나 설정 정보와 같은 단일 객체를 공유해야 할 때 사용됩니다.

Factory Pattern (팩토리 패턴): 객체의 생성을 처리하는 패턴으로, 객체를 생성하기 위한 인터페이스를 정의하고, 서브 클래스에서 어떤 클래스의 인스턴스를 생성할지를 결정합니다. 이를 통해 객체 생성 코드를 클라이언트로부터 분리시킬 수 있습니다.

Observer Pattern (옵저버 패턴): 이벤트 발생 시 관찰자(옵저버)들에게 자동으로 알림을 보내는 패턴입니다. 주로 한 객체의 상태 변화에 따라 다른 객체들이 업데이트되어야 하는 상황에서 사용됩니다.

Strategy Pattern (전략 패턴): 알고리즘을 정의하고, 이를 사용하는 클라이언트와 분리시키는 패턴입니다. 각각의 알고리즘을 캡슐화하고, 런타임 시에 알고리즘을 변경할 수 있습니다.

Decorator Pattern (데코레이터 패턴): 객체의 기능을 동적으로 확장하기 위해 사용되는 패턴입니다. 기존 객체를 감싸는 데코레이터 클래스를 생성하여, 새로운 동작을 추가하거나 변경된 동작을 제공합니다.

Proxy Pattern (프록시 패턴): 실제 객체에 대한 대리자(Proxy)를 제공하는 패턴으로, 클라이언트와 실제 객체 사이에 중간 계층을 두어 추가적인 기능을 제공하거나 접근을 제어할 수 있습니다.

Template Method Pattern (템플릿 메서드 패턴): 알고리즘의 구조

 

Posted by yongary
,

System.in 리딩.

java core 2023. 6. 23. 16:56
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();


첫번재 n을 숫자로 읽고 라인 쭉 읽는 방법.
int n=sc.nextInt();
String []s=new String[n+2];

for(int i=0;i<n;i++){
   s[i]=sc.next();
}
      
기존 방식. 
try {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            int k = 5;
            
            List<Integer> ret = new ArrayList<>();
            while ( k-- > 0) {
                String st = br.readLine();
           }
Posted by yongary
,

java~17

java8~ 2023. 6. 8. 13:07

java8이후 17까지 업데이트된 기능들.

 

 

jshell

immutable Factory

 

var (추론 type)

javac+java -> java

 

람다형 switch  (--enable-preview -source 12 필요?)

 

다중문자열

 

record ( Lombok없이 setter getter자동 추가..)

casting없는 instanceof

 

sealed (class, interface ) : 상속 범위제한

 

Stream.toList() 직접변환 추가. (java 16)

 

람다형 switch : (break도 없어도 됨)

        String typeOfDay = switch (day) {
            case "MON", "TUE", "WED", "THU", "FRI" -> "Weekday";
            case "SAT", "SUN" -> "Weekend";
            default -> "Invalid day";
        };

 

Text Block 추가

String json = """
              {"name": "ChatGPT",
               "type": "AI"
              }
              """;



 

그 외 

java9의 모듈시스템  ( Project Jigsaw 의 결과물로 JPMS 탄생)   참고: https://limdevbasic.tistory.com/21 

 

 

참고: https://www.devkuma.com/docs/java/version/

 

Posted by yongary
,
students.stream()
                .sorted(Comparator.comparing(Student::getCgpa).reversed()
                        .thenComparing(Student::getFirstName)
                        .thenComparing(Student::getId))
                .map(Student::getFirstName)
                .collect(Collectors.toList());

Double을 Checker(Comparator)에서 비교시에는 *100 이런거 하면 안됨. (미세 소수 오류발생)

class Checker implements Comparator<Student> {

    @Override
    public int compare(Student p1, Student p2) { 
        return Double.compare(p2.getScore(),p1.getScore()); //DESC
    }    
}

 

anonymous Comparator 클래스 생성으로 비교하는 법. 1. => compare(int 아니고=> Integer인 부분 주의 필요)

int[] intArr = new int[] {1,2,6, 4, 9, 7};

        List<Integer> sortedInt = Arrays.stream(intArr).boxed()
                .sorted(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer a, Integer b) {
                        return Integer.compare(a,b);
                    }
                 })
                .collect(Collectors.toList());


        log.info(""+sortedInt);

 

 

anonymous Comparator 클래스 생성으로 비교하는 법. 2

        int[] intArr = new int[] {1,2,6, 4, 9, 7};

        int maxInt = Arrays.stream(intArr).boxed()
//                .max(Integer::compare)
                .max(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer a, Integer b) {
                        return Integer.compare(a,b);
                    }
                 })
                .orElse(-1);

 

Posted by yongary
,

List <-> array <-> stream

java8~ 2023. 5. 19. 08:58

1. array <-> stream

int array -> Arrays.stream(.. )으로 바꾸면 intStream()이 되므로 Integer stream으로 바꾸려면 .boxed()를 써야한다. 


    //cards {1,2,2, 7, 9, 9, 8} 중에 pair들 빼고 최대 값구하기
    public static int solutions(int[] cards) {


        Map<Integer, Long> counting = Arrays.stream(cards).boxed()  //intStream()을  stream()으로 바꿔야함
                .collect(Collectors.groupingBy( i->i, Collectors.counting()))  //<Integer, Long>
                ;

        Integer ret = counting.entrySet().stream()
                .filter( e -> e.getValue() == 1)
                .map( e -> e.getKey())
                .max( Integer::compare ) //need STUDY max(Comparator 임)
                .orElse(-1); //.intValue();

        //TEST code: 둘다 오류임 : study필요
//        Integer ret = Arrays.stream(cards).boxed()
//                .max(Comparator.comparingInt());
//                .max(Integer.compare());

        return ret;
    }

ERROR FIX:  Inreger.compare() => Integer::compare     & add.   .orElse(-1) 

Integer::compare 대신에 Comparator.comparing(e -> e) 도 됨. 

Posted by yongary
,