최근에 업무하면서

TaskExecutor과 TaskScheduler를 모두 쓸 일이 있었다

 

그래서 개념에 대해서 깊게 보고싶어서

토비의 스프링을 펼쳐보았다^^7777

역시 이거만한게 없다..

 

정리해보쟛...ㅁ7ㅁ8

 

 


1. TaskExecutor

task실행기.. 그렇담 task는 뭘까?

 

Task : 독립적으로 실행한 가능한 작업

 

스프링은 이러한 task들을 다양하게 실행하도록 추상화하여 TaskExecutor라는 인터페이스를 제공한다.

 

package org.springframework.core.task;

import java.util.concurrent.Executor;

@FunctionalInterface
public interface TaskExecutor extends Executor {
    void execute(Runnable var1);
}

 

java5의 Executor 인터페이스를 상속한다.

 

Runnable타입의 태스크를 받아 실행하는데,

다음 인터페이스는 독립적인 스레드에 의해 실행 되도록 의도된 오브젝트를 만들 때 주로 사용된다.

package java.lang;

@FunctionalInterface
public interface Runnable {
    void run();
}

 

Spring의 TaskExecutor는 java.lang.concurrent 패키지 의 Executor와 똑같은 메소드를 가지고 있다. 

 

package java.util.concurrent;

public interface Executor {
    void execute(Runnable var1);
}

 

그럼에도 스프링에서 다시 만든이유는 다음과 같다.

 

1. 다른 기술의 태스크 실행기에 대한 어댑터를 제공 ( Quartz , CommonJ WorkManager...)

2. 스프링에 최적화된 방식의 태스크 실행기 확장 

 

반드시 비동기 독립적 스레드에서 실행될 필요는 없지만 ,

대부분 비동기로 쓴닷 ㅎ_ㅎ

 

 

2. TaskExecutor 구현체

 

2.1 ThreadPoolExecutor

corePoolSize, maxPoolSize , queueCapacity 속성을 설정할 수 있다.

지정된 크기의 스레드 풀을 이용하며 , 작업 요청은 큐를 통해 관리된다.

가장 대표적인 태스크 실행기다.

 

 

   @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("async-");
        executor.initialize();
        return executor;
    }

 

2.2 SimpleThreadPoolTaskExecutor

Quartz의 SimpleThreadPool을 이용해 만들어진 태스크 실행기이다.

 

2.3 WorkManagerTaskExecutor

CommonJ WorkManager의 태스크 실행기에 대한 어댑터이다.

 

 

2.4 SyncTaskExecutor

별도의 스레드에서 수행되는게 아니라 호출한 스레드 상에서 호출

 

 


3. TaskScheduler 

다음 인터페이스는 주어진 태스크를 조건에 따라 실행하거나 반복하는 작업을 수행

태스크의 실행조건은

1) 특정시간

2) 일정한 간격을 두고 반복

3) Trigger인터페이스를 구현해서 유연한 조건 

 - > cron 서버의 실행시간 설정 포맷을 활용한 cronTrigger가 가장 대표적인 구현 클래스이다. 

 

package org.springframework.scheduling;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
import org.springframework.lang.Nullable;

public interface TaskScheduler {
    @Nullable
    ScheduledFuture<?> schedule(Runnable var1, Trigger var2);

    default ScheduledFuture<?> schedule(Runnable task, Instant startTime) {
        return this.schedule(task, Date.from(startTime));
    }

    ScheduledFuture<?> schedule(Runnable var1, Date var2);

    default ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
        return this.scheduleAtFixedRate(task, Date.from(startTime), period.toMillis());
    }

    ScheduledFuture<?> scheduleAtFixedRate(Runnable var1, Date var2, long var3);

    default ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Duration period) {
        return this.scheduleAtFixedRate(task, period.toMillis());
    }

    ScheduledFuture<?> scheduleAtFixedRate(Runnable var1, long var2);

    default ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
        return this.scheduleWithFixedDelay(task, Date.from(startTime), delay.toMillis());
    }

    ScheduledFuture<?> scheduleWithFixedDelay(Runnable var1, Date var2, long var3);

    default ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Duration delay) {
        return this.scheduleWithFixedDelay(task, delay.toMillis());
    }

    ScheduledFuture<?> scheduleWithFixedDelay(Runnable var1, long var2);
}

 

 

4. TaskScheduler 구현체

 

4.1 ThreadPoolTaskScheduler

JDK의 ShcdeuledThreadPoolExecutor 스케쥴러에 대한 어댑터이다.

 

 

    @Bean
    public TaskScheduler scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("Scheduler-Thread-");
        scheduler.initialize();
        return scheduler;
    }

 

 

4.2 TimerManagerTaskScheduler

 

참고) 유연한 조건을 이용!할때 쓰는 Trigger 인터페이스

 

package org.springframework.scheduling;

import java.util.Date;
import org.springframework.lang.Nullable;

public interface Trigger {
    @Nullable
    Date nextExecutionTime(TriggerContext var1);
}

 

그 Trigger 인터페이스를 구현한 CronTrigger  CronExpression을 지원한다.

package org.springframework.scheduling.support;

import java.util.Date;
import java.util.TimeZone;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

public class CronTrigger implements Trigger {
    private final CronSequenceGenerator sequenceGenerator;

    public CronTrigger(String expression) {
        this.sequenceGenerator = new CronSequenceGenerator(expression);
    }

    public CronTrigger(String expression, TimeZone timeZone) {
        this.sequenceGenerator = new CronSequenceGenerator(expression, timeZone);
    }

    public String getExpression() {
        return this.sequenceGenerator.getExpression();
    }

    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date date = triggerContext.lastCompletionTime();
        if (date != null) {
            Date scheduled = triggerContext.lastScheduledExecutionTime();
            if (scheduled != null && date.before(scheduled)) {
                date = scheduled;
            }
        } else {
            date = new Date();
        }

        return this.sequenceGenerator.next(date);
    }

    public boolean equals(Object other) {
        return this == other || other instanceof CronTrigger && this.sequenceGenerator.equals(((CronTrigger)other).sequenceGenerator);
    }

    public int hashCode() {
        return this.sequenceGenerator.hashCode();
    }

    public String toString() {
        return this.sequenceGenerator.toString();
    }
}

 

 


5. Annotaion 활용 ( @Scheduled , @Async )

 

5.1 @Scheduled

태스크 역할을 맡은 메소드에 직접 스케줄 정보를 어노테이션을 통해 부여해 수케줄이 적용되게 해준다.

@Scheduled 부여되는 메소드는 파라미터를 가질 수 없으며 반드시 void형 리턴 타입이어야한다.

 

-  fixedDelay : 이전 작업이 끝난 시점부터 일정시간이 지난후에 동작하도록 설정 ,

 이전 작업이 끝난후로 부터 정해진 시간이 지난후 다음작업이 시작된다.

@Schduled (fixedDelay=60000)
public void testFixedDelay(){...}

 

- fixedRate : 밀리초로 설정된 일정한 시간간격으로 메소드 실행 

@Schduled (fixedRate=60000)
public void testFixedRate(){...}

 

- cron : Cron expression 으로 메소드 실행

@Schduled (cron = "0 0 12 1 * ?")
public void testCron(){...}

 

 

5.2 @Async 

TaskExecutor를 코드로 사용하지 않고도 비동기 실행이 가능하게 해주는 어노테이션이다.

( 그런데 설정이 필요하면.. Bean으로 만들어주는게 좋다.. threadpool size 등등..)

 

리턴타입은  void 또는 Future 타입이어야한다.

메소드는 다른 코드에 의해 직접 호출 되므로 파라미터를 가질 수 있다. 

 

더자세한 내용은 이전에 포스팅한 이글을 참조한다.

https://hyeonyeee.tistory.com/55

 

Spring에서 Async 처리 (@Async )

Spring에서 Async처리를 해보겠다..! 블로그에 정리되어 있는게 많았는데 그중에 어떤 방법을 택할까 고민을 했다. 가장 간단한 방법으로 구현하였다. @Async annotaion을 붙여주는 방법이다. 1. @EnableAsyn

hyeonyeee.tistory.com

 

 

 


6. 결론

 

정리하다보니 더 자세히 이해가 되었다.

그리고 이전에 개발한 코드가 더 잘 와닿게 되었다 후후

 

그래서 한마디로 정리하자고 하면

 

TaskExecutor는 task를 주로 비동기적으로 처리할때 쓰고

TaskScheduler는 스케줄링할때 쓴다.

 

이 두개 모두 @Async , @Scheduled 라는 어노테이션으로 대체가 가능한데,

자세한 설정이 필요하면

bean으로 만들어 주는것이좋다~ (@Configuraion...)

 

그럼 정리 끝 - 

Backend 개발을 하다보면 인증방식을 결정해야 되는 순간이 꼭 있다.

 

서버와 서버간의 인증

서버와 모바일 서버

아니면 유저가 api서버를 가져다 쓸 때 의 인증 등등..

 

Backend 서버에서 제공해주는 정보를 가져다 쓸 때 인증이 필수 라고 볼 수 있다.

매 HTTP 요청마다 본인이 누구인지 알 수 있는 인증정보를 요청에 포함 시켜 요청해야한다. 

 

그런데 현업에서는 

다양한 아키텍쳐와 비지니스 로직이 있기 때문에

그러한 범위내에서 과연 수많은 인증 방식 중에서 어떤 인증 방법을 택하면 좋을까?

란 고민을 하게된다.

 

어떤 인증 방식을 택하면 좋을지? 를 결정하려면

당연히 어떤 인증방식이 있는지 알면 되지 않을까,,,,

 

란 답으로 시작해서 이번 포스팅을 하게 되었다.

(사실 보안이나 여러가지 개념이 너무너무 헷갈렸다 ^_^; 이러면서 배우는거쥐 뭐~)

 

그리고 Spring Security와 결부시켜서도 얘기해보겠다.

 


1. id + password 방식

가장~~~ 기본이 되고 간단한 방식이다.

그냥 DB에 있는 id와 password 를 요청에서 넣어준 값과 같은지 확인하는 방식이다.

 

여기서 한단계 더 나아가면 password를 암호화정도 하면 되겠다.

 

Spring Security에서도 이부분이 Default인 방식으로 볼 수 있다.

화면 Form에 그냥 id + password 를 담아서 넣어주면 인증이 된다.

 

 

2. Basic Auth

Basic Auth 도 간단한 방법인데

id:password 이 값을 base64로 인코딩한 값을 HTTP 헤더에 담아서보내주면 된다.

Authorization : Basic Base64(id:password)

 

ex) Authorization : Basic VGVycnk6aGVsbG8gd29ybGQ=

 

앞에 Basic을 붙여줘야한다!

 

중간에 패킷을 가로채서 이 헤더를 Base64로 디코딩 하면 id, password가 그대로 노출되기때문에 HTTPS를 쓰는 것을 권장한다.

 

 

3. JWT ( JSON Web Token)

JWT 는 . 을 구분자로 3가지의 문자열로 되어있습니다. 

aaaaaaa.bbbbbb.cccccc

header

payload

signature 

이 각각 세 파트를 각각 다른 방법으로 인코딩하여 HTTP 헤더에 정보를 담아서 넘겨준다.

 

참고

https://sanghaklee.tistory.com/47

 

 

 

 

4. OAuth 

방식은 다섯가지로 grant type이라고 한다.

요새 가장 많이 쓰는 방법이다.

참고

https://hyeonyeee.tistory.com/48

 

 

5. SAML ( Security Assertion Markup Language)

SSO( Sing Sign On) 이 필요할 때 많이 쓰는 인증방식이다.

즉 한번 로그인하면 다른 사이트나 다른 서버에서도 인증이 되는것이다.

하나의 인증으로 다 통합된다는것이다 

얼마나 편리한가,, 사실 이 안의 개념도 엄청 복잡하다.

따로 포스팅 해도 될정도 

 

 

 

ㅎㅎ간단히 보면 이정도 되겠다..

요새는 OAuth나 SAML을 가장 많이 쓰는거 같다.

그래서 그런지 이 두개를 비교하는 포스팅도 많다.

 

Spring Security는 그러면 이 모든 걸 다 제공한다^^

얼마나 방대한가.. ㅎㅎ;

 

사실 이 인증 방식과 Spring Security의 개념이 좀 혼동 되었었는데

이번에 정리 하고 넘어가서 좋다 ^^77

 

화이팅!

 

안의 포스팅은 차차.. 내용을 더 채워 나가도록 하겠다 

 

 

 

 

 

 

1. 서버에서 mysql 로 접속한다.

 

mysql -u root 

mysql -u root -p // 비밀번호 치고 들어가야 할 때

 

 

2. mysql 스키마 변경

use mysql;

 

 

3. user 테이블 조회

select host , user, password from user;

 

4. 계정 생성

create '계정아이디'@'ip' indentified by '비밀번호';

ex)
create user 'test'@'%' IDENTIFIED BY  'test1!';
create user 'test2'@'127.0.0.1' IDENTIFIED BY  'test1!';

 

생성한 user 삭제

 

delete from user where user='test2';

 

 

5. 권한 설정

grant select , insert , update , delete on  스키마명.테이블명 to '계정 아이디 '@'아이피';

grant all privileges on 스키마명.테이블명 to '계정명'@'호스트명' identified by '계정비밀번호' with grant option;

 

첫번째는 주어진거만 , 로 구분해서 권한을 주면 된다.

두번째는 전체 권한이고 

 

 

6. 권한 조회 

show grants for '계정아이디'@'호스트';

ex)
show grants for 'test'@'%';

 

 

7. 권한 삭제

revoke all on '스키마명'.'테이블명' from '계정명'@'호스트';

 

'DEVELOP > DB' 카테고리의 다른 글

[DB] postgreSql Centos7에 설치 및 설정하기  (0) 2020.08.24
[DB]Isolation Level 알아보기  (0) 2020.07.19
[MariaDB] general log 설정하기  (0) 2020.05.25
DB (mysql) 설정 변경  (0) 2020.03.13
NewSql 이란? All in one DBMS  (0) 2019.12.16

MariaDB에는 다양한 로그가 있다.

 

모든 query log가 나올 수 있는 general log가 있고

 

느린 쿼리를 수집하는 slow로그 

 

에러로그를 수집하는 에러로그

 

그중에서 오늘은 general log에 대해서 알아보도록 하자

 

 


1.  root 권한으로 mysql로 접속

우선 서버에서 root 권한으로 들어가준다.

 

mysql -u root 

mysql -u root -p // 비밀번호 치고 들어가야 할 때

 

그리고 mysql로 들어가줌!

 

 

2. general log에 관한 설정 조회

general log에 관한 설정을 조회 해준다.

 

MariaDB [(none)]> show variables like 'general%';
+------------------+-------------------------+
| Variable_name    | Value                   |
+------------------+-------------------------+
| general_log      | OFF                      |
| general_log_file | general.log |
+------------------+-------------------------+

 

 

3. general log 설정 on

set GLOBAL general_log='ON';
set GLOBAL general_log_file='/data/general.log';

이러면 설정은 끝난다.

그치만 매번 DB를 올리고 내릴때마다 같은 설정을 유지하고 싶으니깐

 

my.cnf 파일을 수정해준다.

 

vi /etc/my.cnf

[mysqld]
general_log = 1
general_log_file=/data/general.log

 

만약, 권한이 없으면 sudo 권한으로 열어준다!

( sudo vi /etc/my.cnf )

 

 

default general_log 테이블은 CSV 엔진을 사용하기 때문에 MyIsam 엔진으로 변경한다.

아래와 같은 에러 발생 시 general_log 를 off 시킨 후 수행해야함!

mysql> alter table mysql.general_log engine=MyIsam;

4. 로그 수집 방법 (FILE / TABLE)

 

로그 수집 방법을 조회 해준다.

MariaDB [(none)]> show variables like 'log_output%';
+---------------+------------+
| Variable_name | Value      |
+---------------+------------+
| log_output    | FILE       |
+---------------+------------+
1 row in set (0.001 sec)

 

그런데 나는 로그에서 매번 user_host 즉, ip가 나왔으면 했다.

 

 

그런데 general-log에서는 FILE 로그에서는 connect 할때는 ip가 나오는데 

그 이후, query에서는 나오지 않았다.

 

그런데 table 에서는 기본적으로 user_host가 있으므로 TABLE로 로그를 수집하기로 하였다.

 

cf) 이를 대체하는 방법으로 slow log의 시간을 조정해주는 방법이 있다. 

왜냐면,, slow 로그는 모든 ip를 수집하기 때문이다.

 

SET GLOBAL long_query_time = 0.01;


MariaDB [(none)]> show variables like 'long%';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 0.100000 |
+-----------------+----------+
1 row in set (0.001 sec)


 

 

 

잠시 삼천포에 빠졌었는데 다시 !

그럼 TABLE 에 로그를 쌓도록 수정하겠다.

 

set global log_output='TABLE';

 

그런데 이러면 slow 로그등 다른 로그들도 영향을 받는다.. 그래서 FILE 도쓰고 TABLE도 쓰겠당!

 

set global log_output='TABLE,FILE';

 

그러면 mysql에 general_log라는 테이블이 기본 지원 되기때문에 해당 테이블을 조회 하면 connect , query, 권한 부여등

모든 것이 나온다!

 

 

 

 

event_time	user_host	thread_id	server_id	command_type	argument
03:03.8	root[root] @ localhost []	24	1	Query	show variables like '%log%'

 

 

'DEVELOP > DB' 카테고리의 다른 글

[DB]Isolation Level 알아보기  (0) 2020.07.19
[mySql] 계정 생성 및 권한 설정  (0) 2020.05.25
DB (mysql) 설정 변경  (0) 2020.03.13
NewSql 이란? All in one DBMS  (0) 2019.12.16
NoSql DB 종류  (0) 2019.12.13

이전에 OAuth 2.0에 대해서 정리하는 글을 올렸었다.

그렇다면 Spring 에서 OAuth를 어떻게 구현할까?

 

그게 바로 Spring Security인데 그것에 대해서 알아보고자한다.

 

OAuth와 Spring Security는 여러번 보았는데

볼때마다 헷갈리고 다시 공부하는 느낌이다

 

부디 이번에 조금이나마 더 정리되길 바라며,,, 포스팅 시작한닷..ㅁ7ㅁ8

 


1. OAuth란?

Open Authorization , Open Authentication ( Open 인증 , Open 인가) 로

자신의 애플리케이션 서버의 데이터를 다른 Third Party 에게 공유나 인증을 처리해줄 수 있는 오픈 표준 프로토콜이다

 

즉,,

내 서버의 어플리케이션에 접근 하려면 인증을 거쳐야 하는데, 

이것의 표준이라고 생각하면 된다 ( 인증 & 인가)

 

이 개념이 궁금하면?

https://hyeonyeee.tistory.com/48

 

OAuth 2.0이란?

Oauth 2.0 는 무엇인가,, 알아보겠다 이전엔 보통 open api를 이용할때 토큰을 받아와서 헤더값이 넣어주는 걸 즉, 토큰값을 받아오는걸 구현한 방식이 OAuth 라고 알고있었다 이것도 맞지만 더 자세히

hyeonyeee.tistory.com

다음 포스팅을 참고하자.

 

 

2. Spring에서 OAuth 2.0?

OAuth가 오픈 표준 프로토콜이면 , 

Spring에서 OAuth를 구현하려면? 

Spring Security를 쓰면된닷,,!

 

 

 

3. Spring Security

이제 어느 부분을 구현해보면 되는지 알아보자.

다행히 Spring에서는 많은 소스를 제공해준다

엄청 복잡하게 공부할 수도있지만 우선, 나는 간단하게,, 이해해보겠다.

 

5가지 Grant Type중 

Resource Owner Password Credentials 방식으로 구현해보자.

 

여기서 크게 구현해야 될것은 세가지다.

 

 

1. AuthenticationProvider (Interface)

인증을 담당할 클래스를 구현

UserDetailServiceImpl에서 받아은 유저의 정보를 인증이 완료되면 Authentication 객체를 리턴해준다.

 

 

2. UserDetailService (Interface)

UserDetailService를 implements해서 custom UserDetailService를 만들어주어야한다.

user의 정보를 DB에서 받아온다.

 

3. Authentication Provider 추가하기 

 - SecurityConfig extends WebSecurityConfigurerAdapter

 

1번에서 만든 내가만든 인증 클래스를 ProviderManager에게 등록해주어야 한다.

 

 

 

 

 

 

 

 

 


 

참고)

HTTP Basic Auth 
가장 기본적이고 단순한 형태의 인증 방식으로 사용자 ID와 PASSWD를 HTTP Header에 Base64 인코딩 형태로 넣어서 인증을 요청한다.
예를 들어 사용자 ID가 terry이고 PASSWD가 hello world일 때, 다음과 같이 HTTP 헤더에 “terry:hello world”라는 문자열을 Base64 인코딩을해서 “Authorization”이라는 이름의 헤더로 서버에 전송하여 인증을 요청한다.
Authorization: Basic VGVycnk6aGVsbG8gd29ybGQ=
중간에 패킷을 가로채서 이 헤더를 Base64로 디코딩하면 사용자 ID와 PASSWD가 그대로 노출되기 때문에 반드시 HTTPS 프로토콜을 사용해야 한다.

 

 

en.wikipedia.org/wiki/Basic_access_authentication

 

 

 


https://jeong-pro.tistory.com/205

 

로그인 과정으로 살펴보는 스프링 시큐리티 아키텍처(Spring Security Architecture)

Spring Security Architecture 학습 목표 스프링 시큐리티를 처음 배우는 사람 또는 적어도 한 번은 적용해본 사람을 기준으로 "가장 기본이자 뼈대인 구조를 이해한다"는 학습 목표가 있다. 수 많은 블��

jeong-pro.tistory.com

 

https://minwan1.github.io/2018/03/11/2018-03-11-Spring-OAuth%EA%B5%AC%ED%98%84/

 

Wan Blog

WanBlog | 개발블로그

minwan1.github.io

 

https://spring.io/guides/topicals/spring-security-architecture

 

Spring Security Architecture

this topical is designed to be read and comprehended in under an hour, it provides broad coverage of a topic that is possibly nuanced or requires deeper understanding than you would get from a getting started guide

spring.io

 

^^; 예전에

글을 열심히 썼었는데...

ㅠㅠ 다날라갔다 다시 정리하는겸

써야지~

jpa공부해보니 꼭 실제 업무할때 써보고싶었다

그래야 더 잘 느낄 수 있을거 같다.

 

 


1. JPA 란 ? ( 그외 개념들)

JPA (Java Persistence API) : 자바 어플리케이션에서 관계형 데이터 베이스를 사용하는 방식을 정의한 인터페이스

 

JPA가 인터페이스면 이를 구현한 것도 있지 않을까?

그게바로 Hibernate이다.

 

Hibernate : JPA라는 명세의 구현체이다.

 

쉽게 설명하자면, JPA와 Hibernate는 자바의 interface와 interface를 구현한 class와 같은 관계이다.

즉, 반드시 Hibernate를 쓸 필요는 없다. 그런데 대부분 사용하고 있긴하다.

 

 

Spring Data JPA : JPA를 더 쉽고 편하게 사용할 수 있도록 도와주는 모듈이다. 

JPA를 한단계 추상화시킨 Repository라는 인터페이스를 제공한다.

 

대부분 개발할때 Repository를 이용한다,,

 

 

2. JPA를 왜 쓸까?

jpa는 DB와 객체사이를 mapping해주는 중간자 역할을 해준다.

그래서 기존에 jdbc를 쓸때 쿼리를 이용해서 data에 접근하였었는데 

쿼리를 이용하지 않고, 개발할 때 객체지향적인 관점에서만 접근하게 해준다. 그래서 더 효용이 좋다.

 

 

그런데 여기서  쿼리만 써본 사람들은 의문이 들 것이다.

현재 운영되고 있는 복잡한 쿼리들을 어떻게 JPA로 대체할 수 있을까?

나도 이거에 대한 의문점이 있었는데

 

우선, 간단한 조인 같은건 Querydsl로 적용이 가능하다.

 

그리고 애초에 DB설계자체를 객체지향적으로 하면 

애초에 그렇게 복잡한 쿼리가 나오지 않을 거란 설명이 설득력 있었다.

 

아래 참고 블로그에서 특히 JPA를 왜 쓰는지에 대해서 자세히 나와 있었는데

그중 와닿는 말은 다음과 같다.

 

 

JPA로 실무를 하다 보면, 테이블 중심에서 객체 중심으로 개발 패러다임이 변화된다.

테스트, 통합 테스트시에 CRUD를 믿고 간다.(내가 짠 쿼리는 그것 마저 테스트를 거쳐 가야 한다.)
- 이런거 테스트 할 시간에 CRUD 믿고, 핵심 비즈니스 테스트 코드를 열심히 짜자.


빠르게 에러를 발견할 수 있다.
- 컴파일 시점에 대부분 오류를 발견할 수 있다
-최소한 뭐리 문법 실수나 오류는 거의 발생하지 않는다.



 

https://ict-nroo.tistory.com/117

 

다음 블로그에 자세히 나와있으니 읽어보는 것을 추천한다.

 

 

그리고 실제로도 나도 간단한 개발을 해보았는데 혼자서..

쿼리를 짤때 자잘한 문법오류나 매핑해주는 데에서 오타가 나서 

오류가 나거나 하는 사소한 실수를 전혀 신경쓰지 않아도 되어서 좋았다.

 

 

 


https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/

 

JPA, Hibernate, 그리고 Spring Data JPA의 차이점

개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레�

suhwan.dev

https://ict-nroo.tistory.com/117

vi ~/.bashrc

ㅎㅎ..

이렇게 간단한거였다니 ^^;

 

 

1. alias 전체 리스트 뽑을 때

alias

 

 

2. alias 만들때

test라고 alias를 만들어 주었다.

alisa test = "명령어"

 

3. alias 삭제

test란 alias 삭제

unalias test

 

4. alisa 영구등록

vi ~/.bashrc

 

첫번째 줄 이후에 해당 alias 복붙 

# .bashrc
alias test = "명령어"

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
~

 

이후

source ~/.bashrc

 

하면 적용 완료

REST API를 만들면 Swagger를 상당히 많이 사용한다.

그래서 Django 에서도 Swagger를 적용해보고자 한다.

 

그런데.. 하다보니 안되는 부분들을 발견해서 (버전이슈..)

포스팅해본다 ^^;

 

결론부터 말하자면,

django_rest_swagger를 쓰지말고 , drf-yasg를 쓰는 것을 추천한다

 

 

 

처음에 djnago-rest_swagger를 설치 후 , settings.py에 추가하고 

기동하면 

  • AttributeError at /api/docs/ -> 'AutoSchema' object has no attribute 'get_link'

다음과 같은 오류가 난다..

https://github.com/encode/django-rest-framework/issues/6809 

 

해당 글을 참조해서.. settings.py에 다음을 추가하면.. (저글에선 이걸 추가하면 된다는글이 대부분이다 ㅠ)

	REST_FRAMEWORK = {
	...
	'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
	}

 

But,,,

  • django_rest_swagger - 'staticfiles' is not a registered tag library. Must be one of:

다음 오류가 발생,,,, 다시 구글링..

https://stackoverflow.com/questions/59230539/django-rest-swagger-staticfiles-is-not-a-registered-tag-library-must-be-one

The problem is that staticfiles template tag was deprecated in Django 2.2 and is finally removed in Django 3.0

The djagno-rest-swagger package itself is deprecated and is no longer maintained.

Their GitHub repo recommends something like drf-yasg

 

해당글을 보면, staticfiles 템플릿을 Django3.0버전에서 삭제했고, 

django-rest-swagger 패키지는 더이상 관리안한다고한다,,,

그래서 django-rest-swagger GitHub에서도 drf-yasg를 쓰도록 추천한다고 ^^;

 

여러분들~~ 그냥 속편하게 drf-wasg 쓰세염 ^_^

 

 

https://github.com/axnsan12/drf-yasg

을 참조해서 쓰면된닷

 

 

 

1. drf-yasg 설치

pip install -U drf-yasg

 

 

 

2. settings.py 설정

INSTALLED_APPS = [
   ...
   'drf_yasg',
   ...
]

 

 

 

 

3.urls.py 적용

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_url_patterns = [
  path('api/', include('test.urls')),
]
schema_view = get_schema_view(
  openapi.Info(
    title="Django API",
    default_version='v1',
    terms_of_service="https://www.google.com/policies/terms/",
  ),
  public=True,
  permission_classes=(permissions.AllowAny,),
  patterns=schema_url_patterns,
)

urlpatterns = [
  path('admin/', admin.site.urls),
  path('api/', include('test.urls')),
  url(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
  url(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
  url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]



 

 

그러고 기동한뒤 

http://localhost:8000/swagger로 접속하면 잘뜬다

그리고 http://localhost:8000/redoc으로도 접속하면 뜬다.

 

그럼 이만

 

 

'DEVELOP > Backend' 카테고리의 다른 글

Spring Security 에서 OAuth 2.0이란?  (0) 2020.05.18
JPA이란? (전체적인 개념, 느낀점)  (0) 2020.05.18
Django CORS 설정하기  (0) 2020.03.26
python pip Proxy 설정하기  (0) 2020.03.24
Django 시작하기 [3] Django MVC 패턴  (0) 2020.03.18

Django 로 REST Api 를 만들었는데

Front 단이랑 연결을 해야할때 

CORS 오류가 난다.

 

CORS란? (Crosss-Origin Resource Sharing)

웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용하는 구조이다.

 

 

그럼 Django 에서 CORS 처리를 해보자.

 

 

1. django-cors-headers 설치

 

pip install django-cors-headers

 

 

2. settings.py 에 설정 추가

 

INSTALLED_APPS =[
...

'corsheaders', # CORS 관련 추가

]
...

MIDDLEWARE = [

	'corsheaders.middleware.CorsMiddleware',     # CORS 관련 추가
...  
]
...

# CORS 관련 추가
CORS_ORIGIN_WHITELIST = ['http://127.0.0.1:3000'
                         ,'http://localhost:3000']
CORS_ALLOW_CREDENTIALS = True

 

MIDDLEWARE에 CorsMiddleware를 최상단에 기입해준다.

 

CORS_ORIGIN_WHITELIST에 연동할 ip와 포트를 적어준다.

ip와 포트를 적을때 안될때가 있었는데 다음 포스팅을보고 안전하게 두개를 적어 주었다..

 

https://github.com/adamchainz/django-cors-headers/issues/403

 

 

간단쓰하당 ㅎㅎ

역시 모든건 알면 간단하다..

 

React를 공부하다보니깐

compoent의 종류가 두가지가 있었다

Functional compoent와 class component

 

두개의 차이점이 궁금해졌다

 

그래서 알아보고자한다 

 

사실 create-react-app 으로 프로젝트 생성할때 이전에는 class component로

생성 되었던거 같은데 이번엔 functional component로 생성되길래 

오잉또잉??ㅇㅅㅇ???

해서 찾아보게 된것이다,,,

 

후후 이글은 사실

https://medium.com/@Zwenza/functional-vs-class-components-in-react-231e3fbd7108

 

다음글을 거의 해석한것과 다름없다.

 

그럼 시작해보자 꼬고!

 

 


 

1. Functional Component VS Class Component

 

Functional Component : 그냥 Plain javascipt 

function Welcome(props) {
	return <h1>Hello, {props.name}</h1>;
}

 

Class Component

class Welcome extends React.Component {
  render() {
		return <h1>Hello, {this.props.name}</h1>;
	}
}

 

 

2. 차이점 (1) Syntax

Functinal Component Class Component
javascript function extends React

plain javascript 문법을 사용하여 props를 받아들이고 

React element return

render() 사용하여 React element return

 

 

3. 차이점 (2) State

*** React 16.8에 Hooks가 업데이트 되었다.

Functional 에서도 useState로 state를 사용 할 수 있다.

 

 

functional Component에서는 state를 쓸 수 없다. 당연히 setState를 못쓴다.

그렇기 때문에 이전에는 functional Stateless components라고도 불렀다.

 

그래서,,

state를 쓰고 싶으면 Class Component를 써야한다.

 

아니면!

Parent Component로 state를 올려서 functional component에게 props로 내려주어야한다.

 

 

 

3. 차이점 (3) Lifecycle Hooks

*** React 16.8에 Hooks가 업데이트 되었다.

Functional 에서도 useEffet를 사용 할 수 있다.

 

Functional Component에서 lifecycle hokks를 사용하지 못한다. 

state를 사용 못하는 이유와 같은데, Lifecycle hooks는 React에서부터 온 것이기 때문이다.

 

그래서,,

Lifecycle Hooks를 사용 하려면 Class Compnent를 사용해야 한다.

 

 

 

 

4. 그렇다면,,, Functional Component를 왜써???????ㅇㅅㅇ?

 

1. Functional Component는 훨씬 더 쉽게 읽고 테스트 할 수 있다.

  state도 없고, lifecycle도 없이 그냥 javascript 문법이기 때문이다.

2. 코드가 더 적다

3. 코드가 더 간단

4. React Team에서 functional Component 성능을 더 좋아지게 할거랬어,,

 

 

5. 결론

그렇다면,,,

어떻게 사용하는 것이 좋을까?

state 와 lifecycle hooks를 사용할거면 당연히  Class Component를 사용 

사용하지 않는 다면~ Functional Component를 사용 하면 된다.

 

ㅎㅎ; 왜알아본거지

그냥 Functional Component 쓸걸~~ㅎㅎ

 

뭐 자세히 알아보았다 ^_^ㅎㅎ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+ Recent posts