PostgreSQL의 psql은 PostgreSQL 데이터베이스와 상호작용하기 위한 커맨드 라인 툴입니다. psql 내에서는 \로 시작하는 다양한 명령어가 있으며, 이를 메타 명령이라고 부릅니다. 여기 몇 가지 유용한 예제를 소개합니다:

  1. \c [database_name]
    데이터베이스 연결을 변경합니다. 예를 들어, 다른 데이터베이스로 전환하고 싶을 때 사용합니다.
  2. \d [table_name]
    특정 테이블의 스키마를 보여줍니다. 테이블 이름을 생략하면 모든 테이블, 뷰, 인덱스 등의 목록을 보여줍니다.
     
     
  3. \dt
    데이터베이스 내의 모든 테이블을 보여줍니다.
  4. \l
    사용 가능한 모든 데이터베이스의 목록을 보여줍니다.
    \l
  5. \i [filename]
    지정된 파일에서 SQL 명령을 읽어서 실행합니다.
    \i setup.sql
  6. \s [filename]
    psql 세션에서 실행한 명령어의 기록을 파일로 저장하거나 보여줍니다.
    \s commands.log
  7. \e
    기본 텍스트 에디터에서 마지막으로 실행한 SQL 명령을 편집할 수 있습니다. 에디터는 환경변수 EDITOR로 설정됩니다.
  8. \x
    쿼리 결과를 확장된 형식으로 보여줍니다. 컬럼이 많은 경우에 유용합니다.
     
  9. \conninfo
    현재 데이터베이스 연결 정보를 보여줍니다.
     
     
  10. \q
    psql에서 나갑니다.
Posted by yongary
,



CREATE USER otheruser WITH PASSWORD 'password';


GRANT INSERT, UPDATE, DELETE ON othertable TO otheruser;

이렇게만 하면, 기존 사용자는 그대로 crud가 가능한 상태에서,
새로운 특정사용자에게 othertable 특정테이블만  권한을 주게된다. 


(확인)

SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_name='mytable';

 

 

///실 사용예제.

$ psql -h dbURL -U postgres -d postgres
> \c testdb
> CREATE USER otheruser WITH PASSWORD 'test';
> GRANT INSERT, UPDATE, DELETE, SELECT ON monthlydata TO otheruser;

> \c testdb otheruser
> SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_name='monthlydata'

Posted by yongary
,

 

로드밸런서 설정시

HTTPS:443 설정에서 아래처럼 하면 웹서버로는 http가 전달되며, 이를 SSL Termination 이라고 부름.

  • 이 설정에서, 트래픽의 "Default actions"을 웹 서버로 트래픽을 HTTP로 전달하도록 구성합니다. 여기서 SSL 종료가 발생하며, ALB가 SSL/TLS 암호화를 해제하고, 결과적으로 내부 서버에는 암호화되지 않은 HTTP 트래픽으로 데이터를 전송합니다. 이는 내부 네트워크의 보안을 기반으로, 성능 최적화와 구성의 단순화를 도모할 수 있습니다.
  • 대상그룹으로 전달해도 동일한 효과가 발생할 것으로 예상됩니다.

 

참고 - NGINX로 전달한 블로그 : https://medium.com/@vdongbin/aws-elb%EC%99%80-nginx%EB%A1%9C-https-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-736b8c5ee76  

 

Posted by yongary
,

아래 URL을 참고하세요.

 

https://velog.io/@kimsehwan96/S3-CORS-%ED%97%A4%EB%8D%94-%EA%B4%80%EB%A0%A8-%EC%9D%B4%EC%8A%88-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-html2canvas-lottie

Posted by yongary
,

 

Spring Security를 이용해 로그인한 관리자에게만 images를 노출할 수 있습니다.


### build.gradle
implementation 'org.springframework.boot:spring-boot-starter-security'


### 설정
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/images/**").hasRole("ADMIN") // 이미지 리소스에 대한 접근 권한 설정
                .anyRequest().permitAll() // 다른 요청은 모두 허용
                .and()
            .httpBasic(); // 기본 인증 사용
    }
}

### application.properties
spring.security.user.name=admin
spring.security.user.password=adminpassword
spring.security.user.roles=ADMIN

### WebConfig
registry.addResourceHandler("/images/**")
        .addResourceLocations("file://" + System.getProperty("user.dir") + "/my-images/");
 
 
 
### 참고 : 로그인 구현방식 중 1가지 예제:단,  {noop}는 암호화없는 평문이라는걸 알리는 키워드입니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/images/**").hasRole("ADMIN")
                .anyRequest().authenticated() // 모든 요청에 대해 인증을 필요로 함
                .and()
            .formLogin(); // 폼 기반 로그인 사용
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("admin").password("{noop}adminpassword").roles("ADMIN");
    }
}
Posted by yongary
,

 

front에서 직접 이미지를 올리더라도, S3의 bucket URL 및 키를 모두 front에서 관리하는 것은 보안상 위험하므로
Backend에서 pre-signed URL을 프론트로 주면, front에서 그 URL을 이용해서 올리는 방식이 권장된다.
pre-signed URL은 설정한 시간(예: 1시간) 동안 유효하다.

java 백엔드에서 pre-signed URL을 생성하고, front에서 react를 이용해서 파일을 올리는 예제는 다음과 같다.

 



백엔드:  AWS-SDK이용.

import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.util.Date;

@Service
public class S3Service {
    private final AmazonS3 s3Client;
    private final String bucketName;

    public S3Service(
            @Value("${aws.accessKeyId}") String accessKeyId,
            @Value("${aws.secretKey}") String secretKey,
            @Value("${aws.region}") String region,
            @Value("${aws.s3.bucketName}") String bucketName) {
        this.bucketName = bucketName;
        this.s3Client = AmazonS3ClientBuilder
                .standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKeyId, secretKey)))
                .build();
    }

    public URL generatePresignedUrl(String objectKey, HttpMethod httpMethod, long expirationInSeconds) {
        Date expirationDate = new Date(System.currentTimeMillis() + (expirationInSeconds * 1000));
        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey)
                .withMethod(httpMethod)
                .withExpiration(expirationDate);

        return s3Client.generatePresignedUrl(generatePresignedUrlRequest);
    }
}

 

 

FrontEnd:

import React, { useState } from 'react';
import axios from 'axios';

function FileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);

  const handleFileChange = (event) => {
    setSelectedFile(event.target.files[0]);
  };

  const handleUpload = async () => {
    if (!selectedFile) {
      console.log('Please select a file.');
      return;
    }

    try {
      // Replace with your backend API endpoint that generates the Pre-signed URL
      const response = await axios.get('http://your-backend-api/generatePresignedUrl', {
        params: {
          objectKey: 'example.jpg', // 업로드할 객체의 키
          httpMethod: 'PUT', // 업로드할 때 사용할 HTTP 메서드 (PUT 또는 POST)
          expirationInSeconds: 3600, // URL의 유효 기간 (1시간)
        },
      });

      const { url } = response.data;

      // Use the obtained Pre-signed URL to upload the file directly to S3
      await axios.put(url, selectedFile, {
        headers: {
          'Content-Type': selectedFile.type,
        },
      });

      console.log('File uploaded successfully.');
    } catch (error) {
      console.error('Error uploading file:', error);
    }
  };

  return (
    <div>
      <input type="file" onChange={handleFileChange} />
      <button onClick={handleUpload}>Upload</button>
    </div>
  );
}

export default FileUpload;
Posted by yongary
,

postgreSQL array관련

BACK-END 2023. 9. 24. 18:29

postgreSQL에서 array필드를 query할 땐 아래처럼 하면 된다.
(tags가  TEXT[] 필드일 때 가정..==>  INSERT시에는 ARRAY['tag1', 'tag2']) 로 삽입.

 

== MyBatis. xml ===

<select id="getTags" resultType="string">
    SELECT array_agg(tag) AS tags
    FROM (SELECT unnest(tags) AS tag FROM posts) AS subquery
</select>

 

== java 코드 ==

public interface TagMapper {
    List getTags();
}

 

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    TagMapper tagMapper = sqlSession.getMapper(TagMapper.class);
    List<String> tags = tagMapper.getTags();
    
    // 결과(tags)를 처리
} finally {
    sqlSession.close();
}

 

Posted by yongary
,

소프트웨어 아키텍처 패턴

정의

소프트웨어 아키텍처 패턴은 시스템의 전반적인 구조를 설명합니다. 아키텍처 패턴은 시스템의 핵심 구조와 그 구조의 특징을 묘사하며, 대규모 설계 문제를 해결하기 위한 고수준의 템플릿입니다.

종류

  1. 계층형 패턴 (Layered Pattern): 시스템을 독립된 계층으로 나누고 각 계층간의 상호작용을 정의합니다.
     Presentation Layer, Application Layer,  Domain Layer(비즈니스 로직), Infra Layer(데이터베이스 상호작용)

  2. 클라이언트-서버 패턴: 클라이언트와 서버의 역할 분리로 서비스 요청과 처리를 관리합니다.
  3. MVC (Model-View-Controller) 패턴: 사용자 인터페이스와 비즈니스 로직을 분리하여 관리합니다.
     View(사용자 상호작용) -> Controller에서 Model(비지니스 로직)과  View사이의 중계자 역할을 하게 됨. 
  4. 이벤트 버스 패턴: 컴포넌트 간 메시지를 중앙 이벤트 버스를 통해 전달합니다.
  5. 마이크로서비스 패턴: 작은 서비스로 분할하여 독립적으로 운영 및 개발할 수 있게 합니다.
    그 외 6~10번   더 나열하자면...  
    (Master-slave pattern 
    . Pipe-filter pattern  - 파이프를 통해 흐르는 데이터를 중간중간 필터 모듈이 처리하는 패턴. 
    . Broker pattern 
    . Peer-to-peer pattern 
    . Blackboard pattern  - "블랙보드"에 비유되는 중앙 저장소에 데이터를 공유 . 
     (interpreter패턴도 여기 들어갈 수 있는데, 아래꺼랑 헤깔려서 일단 제외)

 

 

SW 디자인 패턴

정의

디자인 패턴은 소프트웨어 설계 단계에서 특정 문제를 해결하는 일반적인 해법을 제공합니다. 디자인 패턴은 보다 구체적이며, 작은 범위의 설계 문제에 적용됩니다.

종류

  1. 생성 패턴: 객체 생성과 관련된 패턴으로, 싱글턴, 팩토리 메서드, 추상 팩토리, 빌더, 프로토타입 등이 있습니다.
  2. 구조 패턴: 객체 간의 구조화된 관계를 설명하는 패턴으로, 어댑터, 브리지, 컴퍼지트, 데코레이터, 퍼사드, 플라이웨이트, 프록시 등이 있습니다.
  3. 행동 패턴: 객체 간의 상호작용과 책임을 다루는 패턴으로, 책임 연쇄, 명령, 해석자, 반복자, 중재자, 메멘토, 옵저버, 상태, 전략, 템플릿 메서드, 방문자 등이 있습니다.

Posted by yongary
,

Redis 의 영속성(persistency):

 - default로 스냅샷(.rdb)파일 옵션이 켜져 있으며, 주기적으로 스냅샷을 찍고, 복구시 이를 이용한다. => 끌 수도있고 설정변경 가능.
       (기본값: 15분, 5분, 1분/key  1개, 10개, 1만개)

- AOF(append only file) 을 설정하면 용량이 크지만 모든 기록을 aof파일에 기록을 하고, 복구시에 사용한다.
   => 데이터 유실 확률이 더 적어지지만, 로딩속도가 늦고,  100%복구는 장담할 수 없다.  (매우 critical한데서는 사용 비추)

 

Rate Limiter: (http 429: too many request 에러 리턴)

- 직접 구현시에는 요청을 Intercepter해서 ConcurrentHashMap 같은데   클라이언트IP+시간키 / 개수 등으로 관리.
   (서버가 여러대일때는 1/n이 되고 약간 부정확)

- 보통은 라우터 단에서 더 많이 하게되는데, 예를 들면 AWS의 API Gateway에서는 api별로 Throttle 옵션을 설정하면 된다.  

  => Stage설정을 통해 전체 API에 대한 요청 제한 관리.

 

- cloudFlair와 같이 전문적으로 제공해 주는 서비스 존재.  AWS의 WAF는 미세설정이 좀 부족했음. 

 

 

서킷 브레이크:

서킷 브레이커(Circuit Breaker) 패턴은 분산된 마이크로서비스 아키텍처에서 일반적으로 사용되는 패턴 중 하나입니다. 이 패턴은 서킷 브레이커가 전기 회로에서 과부하로부터 회로를 보호하는 것과 유사한 방식으로 작동합니다.

온라인 서비스 시스템에서, 한 서비스가 다른 서비스에 의존할 때, 호출되는 서비스가 실패하거나 지연될 경우 전체 시스템에 문제가 생길 수 있습니다. 서킷 브레이커 패턴은 이러한 문제를 방지하기 위해 사용됩니다.

서킷 브레이커는 특정 서비스에 대한 요청이 일정 임계치를 초과하여 실패할 경우, 추가 요청을 차단하고 즉시 실패 응답을 반환합니다. 이렇게 하면 실패한 서비스에 대한 의존성이 전체 시스템에 미치는 영향을 최소화하며, 실패한 서비스가 회복될 시간을 제공합니다.

 

 

 

 

MSA migration:

 

 

 

용어

  - AWS의 CDN = cloudFront : 에지서버(가까운 서버)에서 컨텐츠를 직접 제공.  

  - C.A.P 이론 : CAP 이론은 분산 시스템에서 세 가지 핵심 C.A.P 중 어느 두 가지만을 선택할 수 있다는 개념을 나타내는 이론입니다. 이런 선택은 분산 시스템의 설계와 운영에서 중요한 결정을 내리는 데 영향을 미칩니다.

  1. 일관성(Consistency): 모든 노드가 동시에 같은 데이터를 보는 것입니다. 즉, 어떤 노드가 데이터를 변경하면, 다른 모든 노드도 동일한 데이터를 볼 수 있어야 합니다.
  2. 가용성(Availability): 모든 요청은 성공하거나 실패해야 합니다. 시스템은 항상 요청에 대한 응답을 주어야 합니다. 실패한 노드에 대한 요청도 응답을 반환해야 합니다.
  3. 분할 내성(Partition Tolerance): 네트워크 지역이 분할되고 지역간 통신 실패 같은 상황에서도 시스템이 정상적으로 작동하거나 복구할 수 있어야 함 => Consistency와 바로 상반 됨.

CAP 이론은 "일관성", "가용성", "분할 내성"을 모두 동시에 만족시키는 것은 불가능하다고 주장합니다. 이를 그림으로 나타내면 CAP 이론의 유명한 "CAP 삼각형"이 나옵니다. 이 삼각형에서는 세 속성이 모두 연결되어 있는데, 그 중에서 두 개를 선택할 수 있다는 것을 의미합니다.

CAP 이론은 분산 시스템의 설계와 구축 시 어떤 속성을 우선시할 것인지 결정해야 한다는 중요한 이론

 

- SDLC (S/w Development LIFE Cycle) :  개발을 위한 단계별 접근방식 - Waterfall, agile, V-Model 등이 있다. REF
- SRS (Service Requirement Specification) - 요구사항 정의 느낌.

- SLE (Service Level ObjEctive)의 약자로, 서비스 수준 목표를 나타내는 개념입니다. SLE는 서비스의 성능 및 가용성과 같은 품질 지표를 정의하고 측정하기 위해 사용.    즉:  응답시간, 가용성, 에러비율, 처리량 등. 

 

Posted by yongary
,

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
,

시스템 디자인 + 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
,

ERD 무료 툴 (draw.io)

BACK-END 2023. 2. 28. 19:18

erWin이 가격도 문제이고, 공유기능도 없어서 

초기에 스케치용으로 ERD를 그릴때는 draw.io 가 좋은것 같다. 여러명이서 구글드라이브에 공유해 동시에 그릴 수 있는 장점이 있다.

 

TIP: 

https://drawio-app.com/entity-relationship-diagrams-with-draw-io/ 

 

ERD외에도 다양한 diagram을 그릴 수 있는데,

- 어떤 형태의 Diagram이 좋을까는 여기참고: 

https://velog.io/@yooha9621/UML%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8UML%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8-%EC%A2%85%EB%A5%981

 

 

오라클에서 테이블목록, 엔터티정의서, 테이블정의서 추출 SQL: https://seodaeya.tistory.com/105 

 

# 테이블 목록 조회
SELECT A.TABLE_NAME AS 테이블명 , 
       B.COMMENTS AS 코멘트
  FROM USER_TABLES A
 INNER JOIN USER_TAB_COMMENTS B
    ON A.TABLE_NAME = B.TABLE_NAME
   -- AND A.TABLE_NAME LIKE 'TB_%' -- 네이밍룰 있을경우
   AND INSTR(A.TABLE_NAME,'TEST') = 0  -- TEST 테이블 있으면 제외
 ORDER BY A.TABLE_NAME
 

    
--  테이블 정의서

SELECT
    a.table_name     AS 테이블명,
    --a.tab_cmt        AS 테이블설명,
    a.column_name    AS 컬럼명,
    b.pos            AS PK,
    a.data_type      AS 데이터유형,
    a.DATA_LENGTH    AS 데이터길이,
    a.nullable       AS null여부,
    --,a.column_id      AS 컬럼순서,
    a.data_default   AS 기본값,
    a.col_cmt        AS 컬럼설명
FROM
    (
        SELECT
            s1.table_name,
            s3.comments   AS tab_cmt,
            s1.column_name,
            s2.comments   AS col_cmt,
            s1.data_type,
            CASE
                WHEN s1.data_precision IS NOT NULL THEN
                    data_precision
                    || ','
                    || data_scale
                ELSE
                    to_char(s1.data_length)
            END AS DATA_LENGTH,
            nullable,
            column_id,
            data_default
        FROM
            user_tab_columns    s1,
            user_col_comments   s2,
            user_tab_comments   s3
        WHERE
            s1.table_name = s2.table_name
            AND s1.column_name = s2.column_name
            AND s2.table_name = s3.table_name
            AND S1.TABLE_NAME in (
				SELECT TABLE_NAME from USER_TABLES
    )
    ) a,
    (
        SELECT
            t1.table_name,
            t2.column_name,
            'PK' || position AS pos
        FROM
            (
                SELECT
                    table_name,
                    constraint_name
                FROM
                    user_constraints
                WHERE
                    constraint_type = 'P'
            ) t1,
            (
                SELECT
                    table_name,
                    constraint_name,
                    column_name,
                    position
                FROM
                    user_cons_columns
            ) t2
        WHERE
            t1.table_name = t2.table_name
            AND t1.constraint_name = t2.constraint_name
    ) b
WHERE
    a.table_name = b.table_name (+)
    AND a.column_name = b.column_name (+)
ORDER BY
    a.table_name,
    a.column_id
Posted by yongary
,

기본적인 서버구성이 끝났다면.. (여기서는 2대의 서버에, route53을 통해 도메인 하나 공급을 가정)
  - 기본서버설정(jdk설정) : www.liquidweb.com/kb/install-java-8-on-centos-7/ 

  - ulimit설정    : https://www.baluna.ro/increasing-file-descriptors-and-open-files-limit-in-centos-7/

  - 혹시 efs연동시에는 : docs.aws.amazon.com/efs/latest/ug/efs-onpremises.html 참조. 

  - 타임존 설정: $sudo timedatectl set-timezone Asia/Seoul

  - 로케일 설정: ma.ttias.be/warning-setlocale-lc_ctype-cannot-change-locale-utf-8-no-such-file-or-directory/ 

 

(zooKeeper서버 설정시에는 /root/zookeeper/conf/zoo.cfg 에 자기IP만 0.0.0.0 다른 2서버  IP기재 + /var/zookeeper/myid 를 각각 1,2,3으로 설정)

 

1.    AWS의 ACM을 통해 인증서를 발급 받는다.              (참고: jojoldu.tistory.com/434

 

AWS의 Certificate Manager 로 SSL 인증서 발급 받기

보통 서비스가 소규모라면 1대의 서버에 Nginx를 설치하고 Let's Encrypt 를 설치해서 SSL을 등록합니다. 다만 이럴 경우 트래픽이 늘어 로드밸런서 + 여러 서버 구성으로 확장하기가 쉽지 않습니다.

jojoldu.tistory.com

  - 진행 중, [Route53에서 레코드 생성]버튼이 안나올 경우. 

      =>1방법(잘안됨) :  도메인 구매한 사이트의, 도메인 구성에 가서 CNAME 레코드를 추가한다.
         CNAME :  _990122b262bc3ecxxxx.acm-domainname.com 형태로 key와 value를 추가한다. 
             (hostname은 _990122b262bc3ecxxxx 까지만, . TTL은 3600정도..)
      => 2방법: route53으로 직접가서 호스팅영역(mydomain.com)을 먼저추가하고, AWS에 알려주는 4개
              (예: ns-620.awsdns-1.net.
ns-222.awsdns-31.com.ns-333.awsdns-26.co.uk. ns-444.awsdns-50.org.)
          를 도메인 구매한 사이트의, 도메인 구성에 가서 네임서버 1차,2차,3차,4차 로 설정한다.
           ==> 2방법 이후에 [Route53에서 레코드 생성]버튼이 보이므로, 누르면 된다.

       
     (30분 가량 대기하면 인증서 발급이 된다)

2. 그 후, 로드밸런서를 생성한다.

   로드밸런서 설정에서 타겟그룹을 구성하고, 서버2대를 추가.

 

   로드밸런서의 인증서 선택은 1에서 생성한 인증서를 선택한다. 
   보안그룹은 하나 만들어서 넣거나, 미리 만들어 둔 후 고르면 되고(후자 권장)

 

   라우팅 구성, 대상그룹 선택에서 앞서만든 타겟그룹을 추가하면 된다.  프로토콜은 HTTP로 된다. 

 

3. 로드밸런서 stickiness

   - 로드밸런서로 서버 2대에 부하를 분산할 경우,  접속자가 동일한 서버로 계속 접속되는 게 세션관리나 log측면에서 편하다.

  - 이 기능을 stickiness라고 하는데, AWS에서는 stickiness 세팅을 로드밸런서에 하지 않고,  Target Group에서 한다.


  아래 그림과 같이 Attribute에서 stickiness와 stickiness duration을 세팅하면 된다.    

   

 

4. 마지막으로, route53에 가서 A.레코드 세트를 추가하면서, Alias사용을 선택하면 로드밸런서를 선택할 수 있다.
  이름은 안넣고 하나생성, www 넣고 하나생성 .. 이렇게 A레코드 2개 세트 권장.

Posted by yongary
,

격리수준

BACK-END 2020. 7. 11. 22:15

DB의 트랜잭션은 ACID를 보장해야 한다. (참고: https://feco.tistory.com/45

 - 원자성, 일관석, 격리성, 지속성

Atomicity: 한트랜잭션이 여러query로 이루어질 수 있는데, 한 트랜잭션의 모든 query가 성공하거나, 혹은 part of transaction이 실패하면 전체 transaction이 실패/혹은 rollback해야한다. 
Consistency: 트랜잭션후에도 DB는 항상 valid state 를 유지해야 한다.(for각종 constraint들 enabled in DB)
Isolation : 동시에 여러개의 transaction이 실행되더라도 하나씩 고립되어 순차적으로 실행되어야한다.
Durability: 트랜잭션이 commit되고 나면, 항상 available해야한다. server가 꺼졌다 켜지더라도...

 

 

이중, "I"인 Isolation(격리성의) 수준은 (참고: https://m.blog.naver.com/PostView.nhn?blogId=blueaian&logNo=220636152759&proxyReferer=https:%2F%2Fwww.google.com%2F )

 

- READ UNCOMMITED (dirty read 발생가능 + 아래들)

   : 일반적인 Database에서는 사용하지 않음

- READ COMMITED (none-repeatable read 발생가능 + 아래 )

   : Oracle 트랜잭션 격리 수준 ( OLTP에서 많이 채택 )

   : commit된 데이터에 대해 다른 세션에서 읽을 수 있음

- REPEATABLE READ  (Phantom Read발생가능)

  : Mysql 기본 격리수준

  : select 에 대해서도 MVCC 수준 유지

- SERIALIZABLE

  : 동시성이 중요한 Database에서는 사용하지 않음

 

Posted by yongary
,

SELECT /*%expand*/* FROM (


SELECT
*,

if(@code = service_code, @count := @count + 1, (@count := 0 || @code := service_code)) count

FROM

my_table

WHERE service_code="blabla"

ORDER BY service_code )

WHERE count <=9 ;


이러면 service_code별로 10건씩 소팅이 되서 나온다.   

oracle의 rownum하고 비슷하게 사용한 예제이지만,  service_code별로 번호를 새로시작하도록 한 코드이다. 

Posted by yongary
,

Doma ORM

BACK-END 2017. 7. 12. 16:32

일본에서 많이 사용하고 있는 DOMA라는 ORM이 있다.

문서나 코멘트 등 모든게 일본어라서 일본 외에서 쓰는 건 쉽지 않지만..

일단 쓰게 된다면 비교적 간편하고 가볍게 잘 만들어진 ORM이라는 걸 알 수 있다.


각종 링크들은 다음과 같다. 요즘은 한국어 자동번역이 잘되니 볼만하다.



SQL_문법 REF페이지 



DOMA 개요



Posted by yongary
,

mysql 원격copy

BACK-END 2017. 5. 17. 12:09

옆동료에게 나의 db를 그대로 복사해주고 싶은 경우,


일단 원격 접속을 해야하기 때문에

1.  mysql> grant all privileges on *.* to 'root'@'10.33.%';   동료pc에서 이런식으로 접속 허용을 해준다.


2. $ mysqldump -u root databaseName > temp.sql

3. 동료 mysql에 접속한 후 ( $mysql -h 동료pc_IP  -u root ) 아래명령 실행.

   mysql> create database databaseName

   mysql> use dataBaseName

   mysql> source temp.sql




Posted by yongary
,


REF



mySql에 dateTime을 지정해서 입력하는 경우,


STR_TO_DATE('12-01-2014 00:00:00','%m-%d-%Y %H:%i:%s') 을 사용해서 insert할 수도 있지만

아래와 같이 간단히 숫자로도 가능하다. 



insert into campaign(campaign_code,version,memo,start_at,end_at,created_at,updated_at) values('bogo',1,'test',20170509150000,20170511110000,now(),now());

Posted by yongary
,

각종 DB에러 exception

BACK-END 2017. 4. 25. 16:57

여러가지 DB 관련된 에러를 포함하는 java exception은  DataAccessException으로 보인다.


http://helols.tistory.com/12  

Posted by yongary
,

REF



oracle에서 workbench를 다운로드 해서( GPL 라이선스라 로그인은 필요함)

실행한 후, 


Database메뉴에서 

 => Reverse Engineering을 하면, 




기존시스템의 ERD를 뽑을 수 있게 된다.



Posted by yongary
,

MySQL 시간 비교

BACK-END 2017. 3. 2. 16:30

REF


시간비교시에는 MySQL의 INTERVAL 을 이용하는 것이 가장 편한 것으로 보인다.


예)

WHERE

myTable.datetimefield > now() - INTERVAL 3 DAY (or MONTH or WEEK ) 

==> 그러나, 날짜간에는 빼기 보다는  DATE_SUB를 사용해야 하고.


BETWEEN도 사용이 가능하지만,.. 작은 날짜를 앞에 써야 한다.

WHERE my_date BETWEEN DATE_SUB(now(), INTERVAL 1 WEEK) AND now()

참) 그리고 NULL을 비교할때는,  IS NULL   또는  IS NOT NULL 을 사용해야 한다.



그 외 Doma라는 ORM에서 IF와 같이 쓰는 경우엔 다음과 같이 섞어서 사용할 수도 있다.

service.service_code
/*%if sortKey == @com.linecorp.fortune.constant.ServiceSortKey@NEW */
, IF ( NOW() - INTERVAL 1 WEEK < forum_service.published_at, 1, 0) as is_new
/*%elseif sortKey == @com.linecorp.fortune.constant.ServiceSortKey@ANSWER_TIME */
, IF (forum_service_condition.average_answer_time = 0, 12, forum_service_condition.average_answer_time) as answer_time
/*%end*/


Posted by yongary
,

mysql Enum

BACK-END 2017. 2. 20. 15:35

(테이블 생성시)

  `type` ENUM('paid', 'free') NOT NULL,


(Insert 시) 'String'을 넣거나 index 숫자를 넣을 수도 있음.




Enum 전반적인 설명-REF1:

   

  - 잘못된 값 삽입시 "" 이 삽입됨. index=0

  - NULL은 index도 null임

  - 일반적인 index는 1부터 시작됨. 



Enum을 Where절에 사용:  REF


  -  index 사용시에는 잘 되지만, 일반적으로 사용시에는 string순서로 비교된다.


Posted by yongary
,

mySql Tip

BACK-END 2016. 10. 12. 17:00

참고: mySql에서 

  - Key키워드도 index를 의미한다.  

     (왜 key라고 부르면서 index와 동일한 건지? 이유가 있을텐데.. 아직은 모르겠음)


 

mySQL을 쓰면서 하면안되는 일들 17가지 blog : REF

 

요약하면

- 파티션/복제/Caching계획을 세우기

- Explain포함 Profile링과 벤치마크 쓰기

- 인덱스 layout과 쿼리 cach 이해하기

- Stored procedure보다는 Prepared구문&Dynamic SQL사용

  (MySQL은 한번 연결해서 여러번 사용해야 효율 적)

- AUTO_INCREMENT 꼭 사용

- ON DUPLICATE KEY UPDATE 꼭 사용

 

정도이다.

 

시간을 가지고 개인적인 의견 하나씩 추가 계획.

 

 

Posted by yongary
,