[React.js] cannot resolve 'react-transition-group' 오류 해결 방법



애니메이션 효과같은것들 적용 하려고 했던 react-transition-group이 서버 구동중 에러가 난다.


cannot resolve 'react-transition-group' 라는 에러메세지가 뜨길래


분명히 해당 패키지도 받았고 제대로 추가 시켰는데 왜 못찾는거지?


하고 검색을 해 보았다.


NPM에 올라온 글을 확인해 보니


This package is deprecated and will no longer work with React 16+. We recommend you use CSSTransitionGroup from react-transition-group instead.

In particular, its version 1.1.1 is a drop-in replacement for the last released version of react-addons-css-transition-group.

Run npm install --save react-transition-group@1.1.1, and replace the imports in your code


1
2
3
4
5
// Old 
import CSSTransitionGroup from 'react-addons-css-transition-group';
 
// New 
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
cs



라고 올라와 있었다


내용인 즉슨


리액트 16 이상 버전 부터는 기존에 사용하던걸 지원하지 않고 아얘 동작도 되지 않게 되었으니


새로운 다른걸 써라~


라고 하는 것이다.


쟤네가 설치하라는거 설치 하고 임포트 문장도 아랫것 처럼 바꾸면


오류는 해결이 된다.

[웹보안] 웹보안 1일차 - 오후


쌍용 강북 센터 모의해킹 및 웹보안


웹보안 관련 강의만 세번째 듣는다.


처음엔 KISA에서 듣고 두번쨰는 현대 모비스에서 듣고


세번째로 듣는데 내용은 대동소이 하다






1. 기술적 진단

 - 웹취약점 진단 vs 소스코드 진단



1)웹 취약점 진단


로그인

계정 및 암호 찾기

회원가입

회사소개

공지사항

현장소식



2) 소스코드 진단


정책자료 http://www.moi.go.kr

https://kisa.or.kr




---skip ---


웹취약점 진단기준


https://www.owasp.org

owasp top10, 10개


A1 ~ A10 (스캔레이의 룰정책에 보면 기본적으로 해당 정보가 있다)




진단 기준은 3년단위로 업데이트 된다. - 그러나 굵직한건 거의 동일 내용임



-----------skip -------------


HTTP 프로토콜

request

브라우저/http 프로토콜마다 request셋팅은 달라진다.


request 기타 메소드는 대부분 사용이 안되고 get/post만 가능 하게끔 구성 되어 있다.


restfull서비스 다 허용하면 공격자가 서버에 파일을 변경하거나 입력할 수도 있게 된다.


response (응답)

200: 정상응답

300:페이지이동

400:클라이언트 잘못된 요청

500: 서버쪽 에러


이러한 응답 코드를 노출하게 되면 공격자에게


어느 부분에서 에러가 났는지 알게 해주기 때문에


공격자에게 힌트를 줄 수가 있다.


에러 페이지는 알아서 잘 만들자.






--skip --


http://demo.testfire.net


kisa 관련 보안 수업때 항상 등장하는 사이트.





--skip--


Sql injection


1. 일반  sql 인젝션


http://demo.testfire.net


에서 로그인시에


ID는 대충 누가 봐도 관리자 아이디 일 것 같은 


admin 입력 후


pw는


싱글쿼테이션인 ' 이걸 넣어보고 날려보자


그럼 sql 에러 메세지와 함께 쿼리도 보여 준다


이때 pw입력을


'or'1'='1


이라고 넣어주면


sql에서는 


WHERE ID='admin' AND pw = ''or'1'='1' 


이라고 인식하여 true값을 리턴하게 되며


admin 계정으로 로그인이 된다.





만약 싱글쿼테이션이 url 인코딩되어 전송되는 경우


프록시툴을 이용하여 HTTP 요청을 가로채서 값을 바꾼 후에 전송 한다.




2.블라인드 인젝션


webGoat -- http://localhost./WebGoat/attack?Screen=13&menu=1100




이름의 첫글자가 어떤 글자인지 추측 한다  뒤의 90은 대문자인지 소문자인지 구별하기 위함이며


90보다 작은경우 대문자 90보다 큰 경우 소문자 라고 생각 할 수 있다.


90은 대문자 Z의 아스키 코드값 이다.

1
SELECT ASCII(SUBSTRING(name,1,1)) FROM pins WHERE cc_number = 4321432143214321 > 90
cs



->


1
101 and SELECT ASCII(SUBSTRING(name,1,1)) FROM pins WHERE cc_number = 4321432143214321 > 80
cs




이렇게 날렸을때 리턴되는 값이 밸리드인지 인벨리드인지 보고 글자를 판단 하도록 한다.


이런식으로 반복하다 어느정도 범위가 좁혀지면


1
101 and SELECT ASCII(SUBSTRING(name,1,1)) FROM pins WHERE cc_number = 4321432143214321 = 74
cs


이런식으로 날려준다


74에서 밸리드가 나온다면 아스키코드 74에 해당하는 글자가 4321432143214321라는 


계좌번호의 주인 이름의 첫글자 라는 것을 알 수 있다.


이런식으로 substring 뒤쪽의 숫자를 

1
2
3
ASCII(SUBSTRING(name,1,1)) 
ASCII(SUBSTRING(name,2,1)) 
ASCII(SUBSTRING(name,3,1))
cs


등으로 바꿔가면서  


한글자식 알아내면 해당 계좌번호의


주인 이름을 전부 알아 낼 수 있다.



다운로드 취약점


서버에 중요한 정보인 config 류의 파일이나


권한,DB접속 정보들이 있는 xml파일을 암호화 하거나 추가적인 권한조치를 취하지 않으면


다운로드 취약점이 발견되는 경우 해당 중요정보가 있는 파일을 다운 받아 해당 서버및 웹어플리케이션


중요정보를 공격자가 알 수 있게 된다




http://localhost./WebGoat/attack?Screen=57&menu=200


Bypass a Path Based Access Control Scheme

프록시툴을 이용해 특정 파일을 요청하는 패킷을 가로채


상대경로로 바꾼 후 톰캣 정보를 가져 올 수 있게 된다.


대충 프로젝트 몇개 하다보면 대부분의 웹어플리케이션의 폴더구조는


비슷비슷 하다는걸 알기 때문에 아래와 같이 추측이 가능 하다


ex) File=../../../tomcat/conf/tomcat-users.xml&SUBMIT=View+File


해당 파일의 정확한 위치를 알 수는 없지만 상대경로를 통해 올라가다 보면


얻어걸리기 때문에 중요 정보를 가져 올 수 있다.



서버보안 이전에 어플리케이션에서 저런 상대경로 요청을 막거나 중요 파일의 암호화를


하지 않은 경우 어렵지 않게 중요 정보가 공격자에게 노출 될 수 있다.




sql MAp 사용



sqlmap 타겟의 디비정보를 뽑아오는 유틸


파이썬기반이기 떄문에 파이썬을 설치 후 사용 하자


파이썬 2점대 버전으로 설치 하도록 하자



사용 방법에 대한 관련 블로그

https://brunch.co.kr/@leesmain/8




테스트 사이트


http://testphp.vulnweb.com



SQLMAP 명령어



 sqlmap.py -u http://testphp.vulnweb.com/AJAX/infoartist.php?id=1 -v 3



뒤에 옵션을 -all --batch 로 주면


모든 공격을 다함



Session 


http 는 stateless 프로토콜이다


그런데도 사용 하는 이유는 가볍고 빠르기 때문에


웹서비스에 적합하기 때문이다.


stateless이기 떄문에 클라이언트가 어떤놈인지 구분할줄 몰라서


http 에서 히든태그를 계속 날려줬었다


그런데 그건 보안에 취약하다


그러니까 히든태그에 담는 데이터를


넷스케이프에서 만든 쿠키에 담기 시작했다


그런데 사실 이것도 보안에 안좋음 


클라이언트 로컬에 저장하기 떄문이다. 게다가 문자열정보만 저장 할 수 있다.


정 쿠키를 쓸떄는 httpOnly를 사용 하도록 한다.


그러니까


세션에 담아서 사용 하도록 하자






[웹보안] 웹보안 1일차 - 오전


2017.05.20 

강북 쌍용 교육센터 웹 보안 기록용 포스팅 입니다.


- 교재 : 해킹 초보를 위한 웹 공격과 방어,

웹 모의해킹 및 시큐어코딩 진단 가이드.



보안에는


클라이언트 , 네트워크 , 시스템, DB정보, 문서 위변조 방지에 관련 한 것이 있다.



해당 글은


웹 어플리케이션 구현 단계에서의 보안에 포커스가 맞춰져 있다.



프록시 툴 : request/response 정보를 변경 할 수 있는 툴

Client-> Proxy Tool->IDS/IPS

IDS/IPS -> Proxy Tool -> Client


버프슈트, 파로스,스캔레이 등 여러가지 툴이 있다.


특정기능은 유료구매를 해야 한다던가 32비트 환경에서만 작동된다던가 하는 툴들이 있으니


알아서 잘 선택 하자.



이번에 사용할 프록시툴은


Scan-Ray 라는 툴을 사용할 것이다.


http://trinitysoft.co.kr/


이곳에서 스캔레이를 받아서 설치를 하면 된다.


구동 환경은 JDK 환경에서 구동 가능 하다.


교육용으로 배포되는 툴이니 알아서 사용 하도록 하자.


설치파일 실행은 관리자 권한 으로 실행 하도록 한다.


일반설치를 하게 되면 write기능이 안먹힌다.



스캔레이 사용 방법



체인 모양 - 프록시 연결 설정임. 짱편함 인터넷 옵션에서 프록시 체크 안해도됨


URL다운모양 - 뭘 써먹을 수 있는지 목록 보여줌


체크판떼기 - 룰설정임 근데 기본적으로 다 체크한 상태로 점검 해보자


지구본검색모양 - 해당 사이트에 공격을 해봐서 취약점 리스트를 뽑아줌.


그래프모양 - 취약점 리포트를 보여준다




테스트 사이트


아무데서나 프록시툴로 변조해서 공격하면 해당 보안팀이나 회사에서 연락 올테니


공격테스트 해보라고 오픈 해놓은 테스트 사이트를 이용 하도록 하자


http://demo.testfire.net

http://www.vulnweb.com



WebGoat


webGoat 도 받아보도록 하자. 보안관력 공격해보고 수정해보고 씹뜯맛즐 할 수 있는 프로젝트다.


https://github.com/WebGoat/WebGoat-Legacy


여기서 받으면 된다.



오라클 설치 되어있으면 8080말고 80으로 시작하자


http://localhost./WebGoat/attack

접속 하면


id:guest

pw:guest


이걸로 로그인 한다.


localhost 뒤에 . 이 붙는 이유는 프록시 어쩌구 했는데 기억 안남. ㅅㄱ










[MSSQL] 프로시저 트리거 while 반복문, 변수값 컬럼명으로 사용하는 방법





1
2
3
4
5
6
7
8
9
10
11
12
declare @colCount int, @colNum int, @columnName CHAR(8) -- 변수 선언
set @colCount = 0
 
while @colCount < 24 -- 반복문 시작
    begin
        SET @columnName = 'T' -- 변수를 컬럼명으로 사용하기 위한 변수
        IF @colCount < 10 BEGIN
            SET @columnName = 'T0' -- 컬럼명이 T00 T01 T02 이런식일때 
        END
        exec ('select ' + @columnName + @colCount + 'into tValData from T_TABLE_NAME')
        set @colCount = @colCount +1 -- 
    end -- 반복문 끝
cs



테이블의 컬럼명이 T00 T01 이런식으로 될떄가 있다.


for문을 돌리고 싶다거나 변수값을 컬럼명으로 사용하고 싶을땐 위와 같이 사용 하면 된다.

[Spring] MyBatis Batch + Transaction 을 이용한 대용량 SQL작업


마을에서 오크잡는 퀘스트 하고 있는데 갑자기


중간보스를 잡아오라는 퀘스트가 떨어졌다...



일정시간마다 라즈베리파이에서 받아온 원시데이터를 재가공하여


DB에 insert 해주어야 하는 작업


로우수가 적다면 그냥 만들겠지만 대용량 작업일 경우 답이 안나온다.


약 1만건~10만건 정도의 데이터를 날려줘야 하는데 ㅂㄷㅂㄷㅂㄷ


그래서 찾아본 방법은 Batch와 Transaction 을 이용한 대용량 sql 작업



나도 정확히 내가 뭘 한건지도 모르고 그냥 스택오버 플로우, 오키, 전자정부 뒤적거리면서 이것 저것 다 때려 박느라

필요 없는 설정이 있을 수도 있으니 아는 사람은 댓글좀 달아주시길 바랍니다.



1.  XML 설정


1) mapper 설정

context-mapper.xml 파일이나 context-sqlMap.xml 파일에


마이바티스 연동을 위해 만들어놨던 설정을 아래와 같이 바꿔준다.


9번 라인의 batch설정으로 batch 사용이 가능 하도록 하는 듯 하다.


1
2
3
4
5
6
7
8
9
10
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/egovframework/sqlmap/example/sql-mapper-config.xml" />
        <property name="mapperLocations" value="classpath:/egovframework/sqlmap/example/mappers/mssql/*.xml" />
    </bean>
 
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
        <constructor-arg index="0" ref="sqlSession" />      
        <constructor-arg index="1" value="BATCH" />
    </bean>
cs



2) datasource 설정

DB접속 정보 작성하는 곳에 트렌젝션메니저 설정을 하는데 이걸 해야 하는 건진 잘 모르겠다.


1
2
3
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
cs



3) dispatcher-servlet 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:task="http://www.springframework.org/schema/task" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-4.0.xsd
                http://www.springframework.org/schema/task
                http://www.springframework.org/schema/task/spring-task.xsd
                http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
 
<tx:annotation-driven proxy-target-class="true"/>
cs


7번 라인과 17번 라인을 추가해주고 20번라인의 내용을 넣어 주도록 한다.



4) pom.xml


1
2
3
4
5
6
7
8
<!-- 트랜젝션 처리를 위함 -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
cs



디펜던시에 추가를 해줘야 트랜젝션 처리가 가능한건진 모르겠음. 전자정부 자체에 관련된게 이미 추가 되어 있을 수도 있고

정확히 모르겠음 저건



2. DAO or impl 작성


나는 DAO를 사용하지 않고 공통DAO하나 만들어 놓고 impl에서 바로 쿼리를 날려주는 방식을

좋아 한다.


어차피 DAO에서 특별히 해줄것도 없고.. 해줘야 하는것이 있어도 impl에서 해주면 되니까



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
    public void updateSchedulerHistoryRow(List<MinHistoryVO> historyList) {
        // TODO Auto-generated method stub
        
       // 트렌젝션 시작
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        long startTime = System.currentTimeMillis();
            try {
                
                for (MinHistoryVO list : historyList) {                     
                    sqlSession.update("scheduler.updateSchedulerHistoryRow", list);
                }
 
            } finally {
                sqlSession.flushStatements();
                sqlSession.close();
            }
 
        long endTime = System.currentTimeMillis();
        long resutTime = endTime - startTime;
        System.out.println("트랜젝션 배치" + " 소요시간  : " + resutTime/1000 + "(ms)");
    }
cs



난 이런식으로 작성 했다.


가끔 6번 라인에 ExecutorType.BATCH 이 매개변수를 안넣고 시작 할 수 있는데

그러면 트렌젝션 안돌고 커넥션 다 찍으면서 돌게 된다.


저렇게 해도 수만건이 돌게 되면 세션에저장될 데이터들이 넘쳐흘러서 그런지 버벅거릴때가 있는데


그럴땐 컨트롤러에서 조금씩 끊어서 날려 주도록 하자



3. controller


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
        //컨트롤러에서 일정 개수 단위로 끊어서 날려 준다.
        int insertCount = 0;
        List<MinHistoryVO> divHisList  = new ArrayList<MinHistoryVO>();
        for(int hisCount = 0, hisSize = historyList.size(); hisCount < hisSize; hisCount++){
            MinHistoryVO _tempData = new MinHistoryVO();
            _tempData = historyList.get(hisCount);
            divHisList.add(_tempData);
            if(insertCount == 1000 || hisSize-1 == hisCount){
                schedulerService.updateSchedulerHistoryRow(divHisList); // 트렌젝션
                divHisList =  new ArrayList<MinHistoryVO>();
                insertCount = 0;
            }
            else{                    
                insertCount++;
            }
        }
cs



while문 사용하는게 익숙하지 않아서 나는 for문을 주로 사용 한다.

리스트에 잔뜩 있는 데이터들을 새로운 작은 바구니에 담아서 끊어서 날려준다.








이렇게 하면 MsSql Server 2005버전 기준 1만건 insert하는데 5초정도 걸린다.


저기에  마이바티스 foreach까지 써서 벌크인서트 하면 시간은 더 단축 된다.


원시데이터를 쪼개서 60개컬럼에 따로 박아야 하기 때문에


넘겨주는 파라미터 개수 2100개 제한이 있어서 제대로 사용 못했는데


여러개로 쪼갠다음에  Mybatis foreach 돌려서 한번에 날려주면 시간은


훨씬 더더더더더 단축 된다.





Socket.IO 자기 브라우저 에서만 emit 되는 현상 해결 방법


남는시간에 react를 공부해 보고자 튜토리얼들을 보고 난 후


실시간 채팅기능을 만들어 보고자


socket.io를 사용 하게 되었다.


여러가지 React Socket.io 라든지  Socket.io React 라던지 여러가지 많았는데 이것 저것 삽질 하다가


그냥 원래 node.js에서 잠깐 만들었던 방법으로 socket.io만 사용해서 구현 하기로 했다.


그런데 분명히 코딩도 제대로 했고


브라우저에서 emit 날려주면 날린 브라우저에서는 값을 다시 제대로 받아 오는데


다른 브라우저에서 날려준 값을 받아오지 못하는게 아닌가


반나절을 삽질을 하다가


socket.io 레퍼런스 사이트를 들어가 하나씩 들춰 보기 시작했다.


.

.

.

.


세상에....


한달사이에 또 무언가 바뀌어 있었다 ㅋㅋㅋㅋㅋㅋ



view단에서가 아니라 server단에서 바뀐게 있었다


기존에 서버에 작성했던 코드는


1
2
3
4
5
6
7
8
9
// 소켓 통신 관련
var io = require('socket.io').listen(3303);
console.log("socket server run!!");
 
io.sockets.on("connection"function(socket){
  socket.on('private'function(msg){ // 응답
    socket.emit('private',msg); // 요청
  });
});
cs



이런식이었다. 그런데 이게 업데이트 되면서


위와 같이 작성한 소켓통신은 통신을 요청한 브라우저 에서만 다시 서버에서 요청을 날려주는 것 이었다.


응답은 받지만 다시 클라이언트로 요청을 날려주는건 요청한 브라우저에게만 날려 주는 것.



접속한 모두가 서버로 부터 요청을 받기 위한 방법


1
2
3
4
5
6
7
8
9
10
// 소켓 통신 관련
var io = require('socket.io').listen(3303);
console.log("socket server run!!");
 
// 커넥션된 모드에게 날려주는 것
io.on('connection'function(socket){
  socket.on('chat'function(msg){
    io.emit('chat', msg);
  });
});
cs


서버에서 이렇게 작성을 해 주어야 한다.



뭐가 다른지 햇갈린다면 두개를 동시에 비교 해 보도록 하자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 소켓 통신 관련
var io = require('socket.io').listen(3303);
console.log("socket server run!!");
 
// 소켓 통신 날린 사람만 받을 수 있는 것.
io.sockets.on("connection"function(socket){
  socket.on('private'function(msg){ // 응답
    socket.emit('private',msg); // 요청
  });
});
 
 
// 커넥션된 모드에게 날려주는 것
io.on('connection'function(socket){
  socket.on('chat'function(msg){
    io.emit('chat', msg);
  });
});
cs



위는 날린 사람에게만 날려주는 것


아래는 모두에게 날려주는 것


커넥션을 할때 io.sockets.on 과 io.on의 차이 였다.


물론 이렇게 한다면 개인적인 소켓통신을 하도록 하는 것이 더 편해지는 것 같다.






[MSSQL]Insert실행시 자동증가되는 IDENTITY값 바로 가져오기



insert를 실행시키고 자동으로 증가 되도록 해놓은 PK값이 바로 필요한 경우가 있다.


A테이블에 값이 입력되면 그 값에 종속되는 B테이블의 값을 넣어야 하는데


PK를 알아오기 위해서 insert후 다시 select 하더라도 한 컨트롤러에서 해결하기란 힘들다.


게다가 해당 pk값을 모르기 때문에 다시 select 하는 것도 문제.


해결 방법


1
2
SELECT @@IDENTITY
 
cs

이걸 사용 하는 것 이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
 
INSERT INTO 
        T_AUTH
        (
         VAL1
        ,VAL2
        ,VAL3)
values(
        #{VAL1}
        ,#{VAL2}
        ,#{VAL3})
 
SELECT @@IDENTITY AS SEQ
cs



이런식으로 사용 하면


SEQ라는 컬럼에 자동증가된 값을 반환 한다


참고로 MYBAITIS에서는


INSERT가 아니라 SELECT로 감싸줘야 정상 작동 한다


예를 들어


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="insertAuth" parameterType="VO" resultType="VO">
    INSERT INTO 
        T_AUTH
        (
         VAL1
        ,VAL2
        ,VAL3)
    values(
        #{VAL1}
        ,#{VAL2}
        ,#{VAL3})
 
    SELECT @@IDENTITY AS SEQ
</select> 
cs



이런식으로 만들면 VO SEQ에 해당 값이 담겨서 리턴 된다.

react-router v4  browserHistory.push 오류 해결 방법


리엑트 라우터가 버전3에서 버전4로 올라감에 따라 


엄청나게 많은 것들이 변했다.


지금 새로운 프로젝트를 만들고 새로운 버전의


패키지들을 받은 후 코딩을 하려면 불과 한달전에 공부했던 코드들이 동작하지 않게 되었다.



망할.. 예전 webpack 버전1에서 2버전으로 올라가면서 바뀐거 찾아내느라 생고생 했는데



이젠 react-router가 문제다




Link를 사용하지 않고 바로 함수 내에서 리다이렉트를 시키는 방법으로


v3에서는 



1
browserHistory.push('/');
cs


이렇게 사용 하였으나


v4에선


Uncaught (in promise) ReferenceError: browserHistory is not defined


브라우저 콘솔창에 위와 같은 에러 메세지가 나타난다.


해결방법


생각보다 간단했다. 위의 코드 대신에


1
this.props.history.push('/');
cs



이렇게 사용해주면 된다.


물론 상단에 리엑트 라우터를 임포트시킬 필요는 없다.


그냥 기능이 넘어와 버린건지 정확하게는 알 수 없지만


깃터브를 뒤져보니 아래와 같은 의견을 찾았다.


걍 이전버전에서는 됐는데 v4에선 안된다 라는 말 같다.





@wyze @timdorr first of all thanks for the v4. I have a few questions and I could not find any solutions for this anywhere, so asking here.

In the earlier versions of the react-router, we could push the the URL using browserHistroy.push() method. When you use browserHistroy the query which you pass, will be transformed to the search key in the history object. The below is an example which used to work in earlier versions.

let query = {
  reportType: 'summary',
  timeZone: 'UTC'
}
  browserHistroy.push({
    pathname: 'some_path',
    query
  })

This will resolve the URL to - test.com/some_path/?reportType=summary&timeZone=UTC

In the current version (v4), it is not possible to pass the query object to the history.push() method.

  histroy.push({
    pathname: 'some_path',
    query
  })

This will resolve the URL to - test.com/some_path/

How to get this working with v4.

MongoDB 기본 명령어


설치방법은 여러군데 소개되어 있으니 패스.


1. 접속 방법


C:\Program Files\MongoDB\Server\3.2\bin



윈도우에서 몽고DB 설치 경로의 bin 폴더를 환경변수 path에 등록하지 않았다면 


CMD에서 해당 경로로 이동후


만약 path설정 했다면 아무데서나 


1
> mongod
cs



라는 명령어로 몽고DB 서버를 실행 시킨다


그 이후


1
> mongo

cs


명령어로 접속 하면 된다.






2. 데이터베이스 생성



1
> use yamea_db
cs



use db명


이런식으로 DB를 생성해 줄 수 있다


현재 사용중인 DB를 확인 하려면


1
> db
cs



db라는 명령으를 사용하면 현재 사용중인 DB명이 나타난다



내가 만든 DB 리스트를 확인하는 방법은


1
> show dbs
cs


show dbs 라는 명령으를 사용 하면 되는데 데이터베이스를 만들자마자


확인하는 경우엔 목록이 뜨지 않는다


최소한 한개 document를 추가 해야 한다


1
> db.book.insert({"name""Yamea MongoDB""author""cheesu"});
cs


이런식으로 추가 하면


디비목록에 보여지게 된다.




3. 데이터베이스 제거


1
2
3
4
 > use yamea_db
switched to db mongodb_tutorial
> db.dropDatabase();
"dropped" : yamea_db "ok" : }
cs


이렇게 use 명령어로 삭제하려는 db 접속후


db.dropDatabase(); 


명령어를 사용하면 데이터베이스 제거를 할 수 있다.




4. 컬렉션 생성


1) createCollection 생성



use 명령어로 DB 접속 후


1
 > db.createCollection("book")
cs


명령어로 생성



2) createCollection + 옵션 생성





1
 > db.createCollection("articles", {capped: true, size: 6142800,max: 10000)}
cs



이렇게 한줄로 쭉 써도 되고


1
2
3
4
5
6
 > db.createCollection("articles", {
... capped: true,
... autoIndex: true,
... size: 6142800,
... max: 10000
... })
cs



이렇게 db.createCollection("articles",{  까지만 입력후 엔터를 쳐서


옵션을 하나씩 추가하는 방법도 가능하다


그런데 현재 버전에서 autoIndex를 포함시키면 에러가 나는데


이유는 모르겠다. 어차피 처음 배우는거니 크게 신경쓰진 말고 이런게 있구나 하고 알아두기만 하자



3) document추가로 인한 자동 생성


createCollection 명령어를 사용하지 않아도 document를 추가 하면 자동으로 컬렉션이 생성 된다.



이렇게 추가 한 컬렉션을 



1
 > show collections
cs


show collections 명령으를 사용하면 만든 컬렉션 목록을 보여주는데




이렇게 나타나게 된다.





5. 컬렉션 제거


컬렉션 제거는 drop() 메소드를 사용 한다.


1
2
3
4
5
6
7
8
9
10
11
> use test
switched to db test
> show collections
articles
book
people
> db.people.drop()
true
> show collections
articles
book
cs



이렇게 하면 people 컬렉션이 사라짐을 확인 할 수 있다.




6. Document 추가


이 Document가 일반 RDBMS에서 말하는 row, data, 행, 


뭐 이런거라고 생각하면 조금 이해가 빠를 거라 생각 된다.



추가 방법은 


1
> db.book.insert({"name""Yamea Guide""author""cheesu"})
cs



이렇게 하나의 다큐먼트를 추가하는 방법과


여러줄을 넣는 방법이 있는데 배열형식으로 전달해 주면 여러 다큐먼트를 동시에 추가 할 수 있다.


1
2
3
4
> db.book.insert([
... {"name""Book1""author""Cheesu"},
... {"name""Book2""author""Yamea"}
... ]);
cs



이런식으로 가능 하며


컬렉션의 다큐먼트 리스트를 확인 하는 방법은


1
> db.book.find()
cs


db.컬렉션이름.find()  이렇게 사용 하면 된다.



이렇게 넣은 document 들을 확인 할 수 있다.




7. Document 제거


db.컬렉션이름.remove(criteria, justOne)


이런 명령어를 사용 하는데


critetia : 삭제할 데이터의 기준값. 이 값이 {} 이면 컬렉션의 모든 데이터를 제거

justOne : 선택적 매개변수이며 이 값이 true면 1개의 다큐먼트만 제거 합니다. 

           생략하면 기본값은 false이며 criteria에 해당되는 모든 다큐먼트들을 제거 한다.



위의 document에서


name이 "yamea Book1"인 Document를 제거 하기 위해선

1
> db.book.remove({"name""Yamea Book1"})
cs



이런 명령어를 사용 하면 된다.





Yame Book1이 사라진걸 확인 할 수 있다.





configuration resolve has an unknown property 'root' path 해결 방법


만약


webpack.config.js 파일에서


경로 작성시 불편함을 해소 하기 위해


resolve: {
root: path.resolve('./src')
},


위와 같은 코드를 사용후


configuration resolve has an unknown property 'root' path 


라는 메세지가 나오며 build할대 에러가 난다면


https://webpack.js.org/guides/migrating/


이곳을 참고 하자



resolve: {
alias: {
Components: path.resolve(__dirname, 'src/components/'),
Containers: path.resolve(__dirname, 'src/containers/')
}
},



이런식으로 alias를 추가해주고 추가한 별칭으로 경로를 사용하면 해결이 된다.



resolve문제인지 모르고 오전내내 삽질하다가


프로젝트를 처음부터 싹 밀어버리고 다시 하나씩 추가해가면서 빌드를 하던중


resolve 문제인걸 알고 한참동안 찾았다.


문서는 항상 진즉에 읽어보도록 하자


webpack1 에서 webpack2로 마이그레이션 되면서


바뀐 부분이 정말 너무 많다;;; 


지금 보고 있는 강좌가 webpack1 일때 작성되었던 강좌라 


설정방법들이 조금씩 다르다.


따로 가르쳐주는 사람이 없으니 정말 맨땅에 헤딩하면서 공부 하는데 


재밌긴 한데 어렵기도 하다.










+ Recent posts