반응형
앞에 글(2018/08/07 - [Development/Tech&Seminar] - #1 Open ID Connect 가 뭐야???에서 OpenID Connect가 무엇인지에 대해서 설명을 했었다. 이번에는 각가의 흐름에 대해서 좀더 자세히 설명을 해보기로 한다. 

OpenID Connect 의 Flow 는 response_type 에 의해서 정해진다고 말했었다. 그 response_type 에 따라서 어떻게 다른지 확인해보자.

아래 정의한 모든 Request는 parameter  scope  openid 가 포함되어야 한다. openid가 포함되어있지 않을 경우는 다르게 동작할 수 있다. 

1. response_type = code

Endpoint

Authorization Code

Access Token

ID Token

Authorization

O

X

X

Token

X

O

O


openid  포함되지 않을경우 (oauth authorization code flow  동일하다)


Endpoint

Authorization Code

Access Token

ID Token

Authorization

O

X

X

Token

X

O

X

 

    2. response_type = id_token (Token Endpoint 를 사용하지 않는다.)

    Endpoint

    Authorization Code

    Access Token

    ID Token

    Authorization

    X

    X

    O

     

    3. response_type = id_token token (Token Endpoint 를 사용하지 않는다.)


      Endpoint

      Authorization Code

      Access Token

      ID Token

      Authorization

      X

      O

      O


      추가적으로 Oauth 2.0 에서는 response_type 에 token 이 라는 항목도 있지만 OpenID Connect 에서는 사용하지 않는다. response_type 이 token 일 경우에는 ID-Token을 리턴하지 않기 때문이다. 

      4. response_type = code id_token

      Endpoint

      Authorization Code

      Access Token

      ID Token

      Authorization

      O

      X

      O

      Token

      X

      O

      O


      5. response_type = code token

      Endpoint

      Authorization Code

      Access Token

      ID Token

      Authorization

      O

      O

      X

      Token

      X

      O

      O


      openid  포함되지 않을경우 (oauth authorization code flow  동일하다)


      Endpoint

      Authorization Code

      Access Token

      ID Token

      Authorization

      O

      O

      X

      Token

      X

      O

      X


      6. response_type = code id_token token

      Endpoint

      Authorization Code

      Access Token

      ID Token

      Authorization

      O

      O

      X

      Token

      X

      O

      O




      참고자료

      http://openid.net/specs/openid-connect-core-1_0.html#IDToken

      https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660


      728x90
      반응형
      반응형

      Open ID Connect 에 대해서 공부하면서 이것저것 찾아본것을 정리해 보았다. 


      1. OpenID Connect 란? 


      - OpenID Connect 는 Oauth 2.0을 확장해서 개발 되었다. 

      OpenID Connect 는 openid라는 scope 값을 포함해서 Authorization Request를 보내며 인증(Authentication) 에 대한 정보는 ID Token 이라고 불리는 JSON Web Token(JWT) 을 리턴해준다.  (scope에 openid 를 무조건 포함해야 하는지는 좀 헷갈린다.. )

      OpenID Provider (OP) : End-User 를 인증하고 인증이벤트 및 End-User에 대한 당사지에게 클레임을 제공할수 있는 Oauth 2.0 인증서버 (원문 : OAuth 2.0 Authorization Server that is capable of Authenticating the End-User and providing Claims to a Relying Party about the Authentication event and the End-User. )



      2. ID Token

      - ID Token 은 End-User의 인증에 대한 Claims 를 담고 있는 암호화 된 토큰이다. ID Token 은 JSON Web Token(JWT) 로 표현된다.


      타입 

       필수여부

       설명

       iss

       Required

       ID Token  발급에 대한 고유 식별값. host, port 등이 포함되기도 한다.

       sub

       Required

       End-User 에 대한 고유한 값

       aud

       Required

       ID Token 과 관련된 청중, client_id 와 관련이 있다.

       exp

       Required

       토큰 만료 시간

       iat

       Required

       JWT 를 발행한 시간

       auth_time

       Required/Optional

       End-User에 대한 인증이 일어난 시간.

       nonce

       

       

       acr

       Optional

       Authentication Context Class Reference. 

       amr

       Optional

       Authentication Method Reference. 

       azp

       Optional

       Authorized Party.

       

      Json Object 예시

        {

         "iss": "https://server.example.com",

         "sub": "24400320",

         "aud": "s6BhdRkqt3",

         "nonce": "n-0S6_WzA2Mj",

         "exp": 1311281970,

         "iat": 1311280970,

         "auth_time": 1311280969,

         "acr": "urn:mace:incommon:iap:silver"

        }



      3. OpenID Connect Authentication Flow

       

      OepnID Connect Authentication 흐름에는 3가지 종류가 있다. 


      1. Authorization Code Flow
      2. Implicit Flow
      3. Hybrid Flow

      우선 이 흐름을 설명하기 전에 아래 표를 먼저 살펴보자. 

       Property 

       Authorization Code Flow

       Implicit Flow 

       Hybrid Flow 

       All tokens returned from Authorization Endpoint

       NO

       YES

       NO

       All tokens returned from Token Endpoint

       YES

       NO

       NO

       Tokens not revealed to User Agent

       YES

       NO

       NO

       Client can be authenticated

       YES

       NO

       YES

       Refresh Token possible

       YES

       NO

       YES

       Communication in one round trip

       NO

       YES

       NO

       Most communication server-to-server

       YES

       NO

       VARIES


      무슨말인지 이해가 안될지도 모르지만 우선 내 생각이 이거 2가지만 기억하면 좋을것 같다. 


      #1 All tokens returned from Authorization Endpoint : token 발급 위치에 대한 내용이다. Oauth 2.0 이나 OpenID Connect 나 정의 되어있는 URL 을 보면 끝에 authorize 로 끝나는 URL 이 있다. (아닐수도 있지만 보통 비슷하다) 이 URL 이 바로 Authorization Endpoint 이다. 먼저 인증이 되었는지 안되었는지 확일을 하는 URL 이고 이 URL 의 응답에 따라서 client 에서는 로그인 창으로 리다이렉트 되기도 한다. 이 값이 NO 라는 말은 Token 발급 Endpoint 가 아니라는 의미이다. 뒤에 또 설명을 하겠지만 간단히 설명하면 Authorization Code 방식은 Authorization Endpoint 에서 인증이 확인되면 Code를 발급하고 그 Code 를 가지고 Token Endpoint로 요청을 해서 Token을 발급받는다.

      #2 All tokens returned from Token Endpoint : URL 이 accessToken 또는 token 이렇게 끝나는 URL 이다. Implicit Flow 같은 경우는 이미 Authorization Endpoint 에서 Token을 발급하기 때문에 Token Endpoint 가 필요 없다. 

      4. Response_type


      위에서 잠깐 언급한 3가지의 Flow Authorization Request response_type 값에 따라서 결정된다. response_type 필수 이다.

       

      response_type value

      Flow

      code

      Authorization Code

      id_token

      Implicit

      id_token token

      Implicit

      code id_token

      Hybrid

      code token

      Hybrid

      code id_token token

      Hybrid

       

      각각의 흐름에 대한 특징들은 다음 글에서 다시 설명하겠다. 


      참고자료

      https://connect2id.com/learn/openid-connect

      http://openid.net/specs/openid-connect-core-1_0.html#IDToken

      https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660


      728x90
      반응형
      반응형

      명령어 절차를 매번 찾기 귀찮아서 이렇게 기록 놓기로 했다.


      1. 먼저 Github에 새로운 Repository 하나를 생성한다.



      2. 실제 repository에 올리고 싶은 프로젝트의 로컬 디렉토리로 이동해서 git init 명령어를 실행한다. 그리고 git status 를 실행하면 아래와 같이 나온다.



      3. git add . 명령어를 실행한다. 



      4. git commit -m "커밋 메세지" 를 실행한다.



      5. 1번에서 만들어 놓았던 repository 의 주소를 복사한다.


      6. git remote add origin 복사한 주소 를 실행한다.


      7. git push -u origin master 를 실행한다. 그런 다음 아무 에러가 안나면 끝난다. 

      그런데 이때 reject 가 나오는 경우가 있다. Git Repository 를 생성할때 ReadeME  파일을 생성하도록 하면 이미 commit 한 내용이 있기 때문에 pull 을 받으라고 나온다.



       그런데 막상 pull을 받으면 아래와 같이 메세지가 나온다.



      이때에는 git pull origin master 라고 입력해주면 된다. 


      그리고 또 혹~~ 시라도 아래와 같은 메세지가 나오는 경우가 있다.


      fatal: refusing to merge unrelated histories


      이 에러는 각각의 history를 가진 프로젝트를 병합 하려고 할때 나온다고 한다. 그럴 경우에는 아래와 같이 옵션을 추가해서 pull을 받아야 한다.


      git pull origin <branch name> --allow-unrelated-histories


      참고 사이트

      https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

      https://hongjinseob.wordpress.com/2017/11/24/git-fatalrefusing-to-merge-unrelated-histories-%ED%95%B4%EA%B2%B0/

      728x90
      반응형
      반응형

      Spring Boot 에서 Properties 를 설정하는 방법에 대해서 알아보자.


      우선 Properties 파일을 3개를 만들어 보았다.

      src/main/resources 하위에 application.properties, application-server1.properties, application-server2.properties 이렇게 3개의 파일을 만들었다.


      application.properties

      1
      2
      3
      4
      application-name: my applicatoin
      spring.output.ansi.enabled=always
      logging.level.org.springframework.web=debug
      server.port=9000
      cs


      application-server1.properties

      1
      server.port=9001
      cs


      application-server2.properties

      1
      server.port=9002
      cs


      일단 이런 상태로 어플리케이션을 실행 시켜서 CommandLineRunner 로 서버 포트랑 application name 을 찍어보았다.


      1
      2
      c.p.s.SpringPropertiesApplication        : application Name : my applicatoin
      c.p.s.SpringPropertiesApplication        : server port : 9000
      cs


      찍히는 것은 당연히 application.properties 파일에 있는 내용들이 찍혀 나온다.


      그럼 이번에는  application.properties  파일에  spring.profiles.active=server1 이라고 입력해보자.


      1
      2
      c.p.s.SpringPropertiesApplication        : application Name : my applicatoin
      c.p.s.SpringPropertiesApplication        : server port : 9001
      cs


      이번에는 application-server1.properties 에 application-name: my applicatoin 9001 이라고 입력해보자.


      1
      2
      c.p.s.SpringPropertiesApplication        : application Name : my applicatoin 9001
      c.p.s.SpringPropertiesApplication        : server port : 9001
      cs


      지금까지 테스트한 결론은 이렇다.


      1. properties 의 profile  을 active 안하면 기본적으로 default properties를 읽는다.

      2. active 한 properties 는 default properties의 값들을 override 한다.


      In addition to application.properties files, profile-specific properties can also be defined by using the following naming convention: application-{profile}.properties. The Environment has a set of default profiles (by default, [default]) that are used if no active profiles are set. In other words, if no profiles are explicitly activated, then properties from application-default.properties are loaded.

      Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones, whether or not the profile-specific files are inside or outside your packaged jar.


      spring boot document 에도 위와 같이 나와있다. 마지막 문장을 번역해보면 다음과 같다.


      profile-specific properties 는 기본적인 application.properties 파일처럼 같은 위치에서 로드된다. 그리고 profile-specific 파일들은 이 파일들이 패키지된 jar파일 안에 있거나 밖에 있거나 상관 없이 non-specific  파일들을 항상 오버라이딩 한다. 


      일단 내가 이 테스트를 통해서 알고 싶었던 것은 이부분이었다. active 한 프로파일이 아예 기존 properties 파일을 교체하는지 아니면 기존 파일에 있는 값들을 유지 하되 중복되는 값들은 override 하는지 알고 싶었다. 결과는 기존값을 유지하고 중복값은 override  한다였다.


      프로젝트를 여러군데 배포하다 보면 배포 환경에 따라서 값들이 변경되는 값들 있다. 편하게 관리를 하려면 profile을 나누는게 확실히 도움이 되는데 항상 우선순위 때문에 헷갈렸다. 물론 properties 파일이 외부에 있는 경우, commandline 으로 들어오는 경우등 여러 가지 케이스가 더 있긴 할테지만 우선 이것으로 내 궁금증은 풀렸다.


      프로젝트 소스 : https://github.com/blusky10/study_spring



      728x90
      반응형
      반응형

      edX사이트에서 Introduction to ReactJS 강의를 들으면서 정리한 내용입니다. 

       

      2018/04/18 - [Development/React] - edX - Introduction to ReactJS Module1 내용정리

       

       

      Class Components

      - Class Component

      Class Component 는 Functional Component 와 다르게 React Component 가 라이프사이클 메소드(Life Cycle method) 와 상태(state) 를 가질수 있도록 해준다. Class Component는 this.state, this.props 를 가지고 있다. 

       

      1
      2
      3
      4
      5
      class Welcome extends React.Component{
          render(){
              return <h1>Hello World!</h1>
          }
      }
      cs

       

      - Render()

      render() 메소드는 Class Component 에서 React Element를 리턴할때 사용된다.

       

      - Adding properties to Class Components

      Class Component의 property는 this.props 를 통해서 접근가능하다. 

       

      1
      2
      3
      4
      5
      class Welcome extends React.Component{
          render(){
              return <h1>Message: {this.props.message}</h1>
          }
      }
      cs

       

      1
      <Welcome message="Hello World!"/>
      cs

       

      State

      - Constructor(props)

      constructor() 메소드는 React Component 가 mount 되기 전에 호출되며 component의 기본 상태를 설정하는데 사용된다. 

      constructor() 메소드 시작에 super(props)를 호출하는것은 중요하다. 안할 경우 this.props 가 정상적으로 동작하지 않을 수 있다. 

      constructor() 메소드의 첫번째 파라메터는 component에 전달되는 속성을 나타낸다. 

       

      1
      2
      3
      4
      5
      6
      7
      8
      class Counter extends React.Component{
          constructor(props){
              super(props)
          }
          render(){
              return <div>Hello World!</div>
          }
      }
      cs

       

      - Adding an initial state to Class Component

      Class Component 의 state 는 반드시 object 형태로 선언되어야 한다. 

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      class Counter extends React.Component{
          constructor(props){
              super(props)
              this.state = {foo:123,bar:456}
          }
          render(){
              return <div>foo:{this.state.foo} bar:{this.state.bar}</div>
          }
      }
      cs

       

      - Updating State

      setState(updater, [callback]) 을 통해서 상태 업데이트가 가능하다. 상태를 업데이트 하는 것은 비동기식이기 때문에 옵션으로 callback 메소드를 호출하게 할수있다. callback 메소드는 업데이트가 완료되면 호출된다. 

      setState 메소드는 component life cycle의 updating 단계를 시작하는 트리거가된다. 이것 때문에 sshouldComponentUpdate() 메소드가 false를 리턴하지 않으면 component가 다시 렌더링 된다. 

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      class Counter extends React.Component{
          constructor(props){
              super(props)
              //initial state set up
              this.state = {message:"initial message"}
          }
          componentDidMount(){
              //updating state
              this.setState({message:"new message"})
          }
          render(){
              return <div>Message:{this.state.message}</div>
          }
      }
      cs

       

      - Updating state based on previous state

      setState() 메소드는 Component의 상태를 즉시 업데이트 하지 않고 큐에 넣어둔 후 나중에 진행된다. 렌더링을 좀더 효율적으로 하기위해서 batch형태로 업데이트 한다. 

      아래 소스에서 setState 메소드를 여러번 호출하지만 state value 는 1만 증가한다. 

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      class Counter extends React.Component{
          constructor(props){
              super(props)
              //initial state set up
              this.state = {value:0}
          }
          componentDidMount(){
              //updating state
              this.setState({value:this.state.value+1})
              this.setState({value:this.state.value+1})
              this.setState({value:this.state.value+1})
              this.setState({value:this.state.value+1})
          }
          render(){
              return <div>Message:{this.state.message}</div>
          }
      }
      cs

       

      setState() 메소드는 첫번재 파라메터로 메소드를 사용할수 있으며 기존 상태와 설정을 넘겨준다.

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      class Counter extends React.Component{
          constructor(props){
              super(props)
              //initial state set up
              this.state = {message:"initial message"}
          }
          componentDidMount()
              //updating state
              this.setState((prevState, props) => {
                  return {message: prevState.message + '!'}
              })
          }
          render(){
              return <div>Message:{this.state.message}</div>
          }
      }
      cs

       

      - State is not mutable

      State 는 오직 읽기만 가능하기 때문에 임의로 변경해서는 안된다. 

       

      Life Cycle Methods

      - Mounting Phase Methods

      mounting 단계는 component가 생성되거나 DOM 에 렌더링할때 시작된다. 

      • constructor(props) : component 가 처음 초기화할때 오직 한번만 호출된다.
      • componentWillMount() : component 가 mount 하려고 할때 호출된다.
      • render() : component가 렌더링 할때 호출된다.
      • componentDidMount() : component 가 mount 된 후에 호출된다.

      - Updating Phase Methods

      updating 단계는 component state 또는 properties 가 변경될때 시작된다.

      • componentWillReceiveProps(nextProps) : component 가 update  되고 새로운 props를 받았을때 호출된다.
      • shouldComponentUpdate(nextProps, nextState) : 새로은 props는 받고 update 하려고 할때 호출된다. 이 메소드가 false 이면 componentWillUpdate(), render(),  componentDidUpdate() 는 실행되지 않는다.
      • componentWillUpdate(nextProps, nextState) : update 될때 호출된다. 
      • render()
      • componentDidUpdate(prevProps, prevState) : update  끝나고 호출된다.

      - Unmounting Phase Methods

      unmounting 단계는 component 가 DOM 에서 제거될때 시작된다. 

      • componentWillUnmount() : component 가 unmount 되고 즉시 호출된다. 

       

      Event Handlers

      - Adding Event Handlers

      React 와 HTML 에서의 이벤트 핸들러 차이

      • React 에서는 JSX {} 을 사용해서 정의한다.
      • React 에서는 이벤트 이름을 쓸때 camelCase 를 사용한다. 
      1
      2
      3
      4
      5
      React
      <button onClick = {clickHandler} >Click Me</button>
       
      HTML
      <button onclick = "clickHandler()" >Click Me</button>
      cs

       

      - Binding Event Handlers to Claas Component

      이벤트 핸들러는 Class Component 내부에 정의 해야 한다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      class Counter extends React.Component{
          constructor(props){
              super(props)
              this.state = {count:0}
              //binding is necessary to make `this` point to the correct object
              this.clickHandler = this.clickHandler.bind(this)
          }
          clickHandler(){
            //increments the count of the state
            this.setState((prevState,props) => {
              return {count: prevState.count + 1}
            })
          }
          render(){
              //renders a button that displays the state count
              return <button onClick = {this.clickHandler}>{this.state.count}</button>
          }
      }
       
      ReactDOM.render(
        <Counter/>,
        document.getElementById("root")
      )
      cs

       

       

      728x90
      반응형
      반응형


      한달 전에 Google Cloud Study Jams 을 진행하는 그룹장을 모집한다는 내용을 보게 되었다. 스터디원도 아니고 그룹장을 모집한다라니. 몇번을 할까말까 고민을 하다가 지원을 하게 되었다. 


      Google Cloud Study Jams 을 통해서 그룹장 및 그룹원들은 Qwiklabs 에서 제공하는 Google Cloud Platform 관련 lab 들을 한달간 무료로 수강을 할수 있는 기회가 제공된다. 그룹장은 같이 스터디를 할 그룹원들을 최소 5명이상 모아야 하며 Google에서 제시한 4가지의 필수 과목을 수료하게 되면 교육을 이수하게 된다. 단, Qwiklabs에서 제공되는 모든 Lab들을 수강할 수 있으며 필수 과목 이외에도 다른 과목을 수강하는것도 허용된다. Qwiklabs에 권한이 크레딧으로 부여되는게 아니라 기간으로 부여되기 때문에 개개인이 듣고 싶은 모든 Labs들을 수강이 가능하다. 


      좋은 기회인것은 분명하고 공부도 하면 좋을것 같아서 회사 내에서 그룹원들을 모집하고 한달간 진행을 했다. 진행이라고 해서 별다른건 없었다. Qwiklabs 자체가 개개인이 Lab을 진행 해야 하기 때문에 그룹원들 보다 먼저 진행해서 좀더 쉽게 할수 있도록 도와주는 역할 정도였다. 그리고 공지사항 같은 것들을 전달하고 하는 역할이었다. 그리고 어느새 한달이 지나갔다.


      2018년 5월 15일 종강모임을 하게 되었다. 원래 참석 대상은 그룹장 대상이었으나 일부 자리가 남아서 그룹원들도 선착순으로 참석할 수 있었다. 장소는 역삼역 GFC 22층 구글 코리아에서 진행 되었다.




      시작에 앞서 먼저 저녁식사가 뷔페식으로 제공되었다. 아마도 구글 직원들이 사용하는 카페테리아 같은데 전에 세미나 들으러 21층은 자주 왔었는데 22층은 처음 와봤다. 그렇게 많지는 않지만 그래도 음식들이 깔끔하고 후식이랑 음료수등로 많이 있어서 배부르게 먹기 충분했다. 


      Google Cloud Study Jams 담당자이신 임성혁 님께서 진행을 하면서 수료식이 시작되었다.

      화면에 보이는 숫자중 위에 있는 것은 전 세계에서 진행된 Google Cloud Study Jams 숫자이고 아래 있는 숫자들인 이번에 처음으로 한국에서 진행된 숫자이다. 첫번재는 참여 인원, 두번째는 그룹 숫자, 세번째는 진행한 시간 네번째는 달성률이다. 짧은 기간 진행된 그룹과 달성률을 전세계 숫자와 비교하면 높은 수치라고 한다. 그만큼 각각의 그룹과 그룹원들의 참여율이 높았다고 할 수 있다.


      이것은 다음에 진행될 Advanced 과정에 대한 예고편이다. 의미심장한 Coursera가 화면에 보인다. 언제 시작될지 아직은 모르지만 벌써부터 기대가 된다. 하지만 전에도 느꼈지만 Coursera 는 이번처럼 만만치는 않을거라 생각이 된다. 

      그리고 이것은 구글에서 준비해준 작은 선물이다. 


      왼쪽에 보이는 것은 티셔츠와 친환경 소재로 만든 연필, 그리고 구글 스티커이다. 이것은 그룹장에게만 준 선물이고 오른쪽에 보이는 배지는 그룹원들에게 주는 선물이다. 



      이번 스터디 기간 동안 내가 진행한 내용이다. 다행히 GCP Essentials 는 완료를 할 수 있었고 그 이외에 Kubernetes 관련된 것도 2개정도 더 들었다. 좀더 많이 들었으면 더 좋았을텐데 라는 아쉬움이 남는다. 그리고 이번에 진행하면서 의사전달을 Slack을 이용했는데 개인적으로는 만족을 했는데 그룹원들에게는 아직 익숙치 않은것 같았다. 그래서 그것때문에 의사전달이 제대로 되지 않은 경우도 발생을 해서 좀 힘이 들었다. 물론 다음 스터디 진행 시에도 Slack을 그대로 사용할 거지만 그때는 좀더 사용을 잘 할 수 있도록 해야겠다. 그리고 어떻게 하면 좀더 즐겁게 많은 것을 배울 수 있도록 참여를 유도할 것인지 고민을 해봐야겠다. 

      728x90
      반응형
      반응형

      백기선님의 Spring Boot 레퍼런스 동영상을 보다 보니 레퍼런스도 한번 쭉~~ 살펴볼 필요가 있겠다 싶은 생각이 들었다. 그럼 뭘 볼까? 라고 생각 하다가 Spring Security 를 보기로 결정 했다. 기간을 가지고 보는것은 아니고 그냥 처음부터 차근차근 정리 하면서 읽어보자라고 생각을 했다. 그런데 보다보니 약간 이상한게 있었다.



      위 내용은 레퍼런스에 나오는 5.2장 HttpSecurity 부분이다. 이상하다고 생각한 부분은 "However ~~~~~" 단락이다. 대체 뭘 어떻게 한다는 의미인지 알수가 없었다. 대체 커스텀 로그인 페이지를 만들때 뭘 조심하라는건지. Url이 RESTFul 한데 뭘 어쩌라는건지. 그리고 정보 유출을 막기위해 Spring security 를 사용하는것이 뭐가 분명하지 않다는것인지 이해가 가지 않았다. 커스텀 로그인 페이지를 만들면 spring security가 해줄수 있는 영역이 분명치 않다는 의미인지.. 그리고 마지막에 "For example" 이 있는데 왜 정작 그 다음에는 예제에 대한 내용은 없는 건지 알수가 없었다. 


      그래서 내용이 궁금하기도 해서 spring security github issue 페이지에 issue를 등록했다. 



      이슈 링크: https://github.com/spring-projects/spring-security/issues/5242#event-1584275921


      그랬더니 issue가 처리 되었다고 메일이 왔다. 그래서 뭐가 어떻게 되었는지 확인을 해보았다. 일단 현재 spring security 5.0.4 Release의 reference는 변경사항이 없다. 그래서 git 을 확인해봤다. 뭐 이런 저런 내용이 있었다. 



      처음에는 내용을 보니 첫 문단에 뭘 drop했다는 건지는 잘 모르겠다. 그런데 다시 넣었고 적절한 방법은 "For example" 을 지우는 거라고 코멘트가 써있었다.

      그리고 그 다음에 또 다른 내용이 있었다.

      내용을 살펴보면 이렇다. 

      그 단락은 Spring Security가 왜 예전의 default URL 과 parameter에서 새로운 것으로 변경했는지 설명하기 위해서 작성한 것이다. 그러데 XML과 Java Config가 동일해서 지금은 더이상 적절하지 않다.

      그래서 결론적으로 

      Restore Example Default URLs and Parameters List to Remove Default URLs and Parameters Commentary

      그 단락을 삭제했다.


      그런데 삭제 했다는데 Reference 에는 아직 존재를 한다. 그래서 다시 Spring Security Github 를 뒤졌다. 


      Commit 로그가 저렇게 있었다. 그래서 세부 내역을 확인해 보았다.



      히스토리를 보니 저렇게 그 부분이 삭제되어 있다. 아마도 다음 레퍼런스에 반영이 되려나 보다. 레퍼런스를 읽다 보니 이런 일도 생기는구나 라는 생각을 했다. 앞으로 차근차근 더 읽어보면서 또 의문나는것이 있으면 자주 이용을 해야겠다.



      728x90
      반응형
      반응형

      edX사이트에서 Introduction to ReactJS 강의를 들으면서 내용을 정리해봤다.


      What is ReactJS?

      ReactJS 는 상태에 따라서 View 레이어를 만들어 주는 라이브러리이다.

      React Compnents는 Virtual DOM 을 생성한다. ReactCompnent의 상태가 변경되면 새로운 Virtual DOM을 생성하고 차이점을 분석한다. 그리고 효과적인 방법으로 HTML  DOM 에 반영한다.


      Rendering Elements

      - React Elements

      React Elements 는 DOM 노드에 표현되는 Object 이다. JSX를 사용해서 syntax를 작성한다. React Elements와 React Components는 다르다. React Elements를  DOM 에 표현하기 위헤서는 ReactDOM.render() 메소드를 사용해야 한다.


      - ReactDOM.render()

      ReactDOM.render() 메소드는 HTML DOM의 특정 부분에 React Elements를  렌더링하는데 사용된다. 대부분 React 어플리케이션에는 한개의 root node 가 있고 그 안에 렌더링 되는데 root node가 여러개 있을수도 있다.


      1
      <div id="root"></div>
      cs


      1
      2
      3
      4
      ReactDOM.render(
              <h1>Hello World!</h1>,
              document.getElementById("root")
      )
      cs


      JSX

      - What is JSX?

      JSX는 Javascript의 syntax 를 확장한 것으로 HTML 태그를 사용해서 Javascript안에 React Elements를 작성할수 있게 해준다.


      1
      var element = <h1>Hello World!</h1>
      cs


      - Using JSX with JavaScript Expressions

      Curly braces ({}) 를 사용해서 표현한다.


      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      var str = "World!" 
      var element =  <h1> Hello {str}</h1>
       
      var item = {
          name"Cheese",
          price: 5
      }
      var element = <p>{item.name} : ${item.price} </p>
       
      var length = 20
      var width = 10
      function calculateArea(x,y){
          return x * y
      }
       
      var element = <div>The Area is: {calculateArea(length,width)}</div>
      cs


      - Using JSX with Attributes

      Attribute 표현시 절대로 curly braces를 quotes("")로 감싸면 안된다. 


      1
       var element = <img src ={product.imageURL}></img>
      cs


      - Style Object

      위에서와 같이 동일하게 style object 를 curly braces  안에 넣어주면 된다.

      1
      2
      3
      4
      5
      6
      7
      var styleObject = {
              backgroundColor: 'red',
              color:'blue',
              fontSize: 25,
              width: 100
      }
      var element = <input style = {styleObject}/>
      cs


      object 로 정의 안하고 바로 사용할 경우에 바깥쪽 {} 는 JSX표현이고 안쪽에 {} 는 style object 를 표현한것이다.

      1
      var element = <input style = {{width:200,height:100}}/>
      cs


      - Nested Elements

      하나로 wrapping  하는 것을 권장한다.

      1
      2
      3
      4
      5
      6
      var element = (
              <div>
                  <div>Hello World</div>
                  <div>Hello World</div>
              </div>
      )
      cs



      Functional Components

      - React Components

      React Components는 독립적이고 재사용 가능한 React Element를 만들어 낸다. React Components는 Functional ComponentsClass Components로 구성된다.


      - Functional Components

      Functional Components는 React Elements를 출력한다. 관습적으로 Function의 첫글자는 대문자로 쓴다.

      1
      2
      3
      4
      5
      6
      7
      8
      function HelloWorld(){
          return <h1>Hello World!</h1>
      }
       
      ReactDOM.render(
          <HelloWorld />,
          document.getElementById("root")
      )
      cs


      - Properties  추가

      Functional Components는 React Elements를 출력한다. 관습적으로 Function의 첫글자는 대문자로 쓴다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      function HelloWorld(props){
          return <h1>Message: {props.message}</h1>
      }
       
      ReactDOM.render(
          <HelloWorld message="Hello World!"/>,
          document.getElementById("root")
      )
       
      cs


      Composition

      - Composing Components

      Functional Components 는 다른 Functional Components 를 결과 값으로 포함할 수 있다. 

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      function ShoppingTitle(props){
          return (
              <div>
                  <h1>{props.title}</h1>
                  <h2>Total Number of Items: {props.numItems}</h2>
              </div>
          ) 
      }
      function ListItem(props){
          return <li>{props.item}</li>
      }
      function ShoppingList(props){
          return (
              <div>
                  <h3>{props.header}</h3>
                  <ol>
                      <ListItem item = {props.items[0]}/>
                      <ListItem item = {props.items[1]}/>
                      <ListItem item = {props.items[2]}/>
                  </ol>
              </div>
          )
      }
      function ShoppingApp(props){
          return (
              <div>
                  <ShoppingTitle title = "My Shopping List" numItems = "9"/>
                  <ShoppingList header = "Food" items = {[ "Apple","Bread","Cheese"]}/>
                  <ShoppingList header = "Clothes" items = {[ "Shirt","Pants","Hat"]}/>
                  <ShoppingList header = "Supplies" items = {[ "Pen","Paper","Glue"]}/>
              </div>
          )
      }
      ReactDOM.render(
          <ShoppingApp/>,
          document.getElementById("root")
      )
      cs


      Conditional Rendering

      - Conditional Rendering

      Functional Components 의 결과값을 프로퍼티에 따라서 결정할 수 있다. 

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      function Feature(props){
          if (props.active == true){
              return <h1>This feature is active</h1>
          }
          else{
              return <h1>This feature is not active</h1>
          }
       
      }
       
      function Feature(props){
          return <h1>This feature is {props.active? "active" : "not active"}</h1>
      }   
      cs


      Module 1 내용 정리 끝.


      728x90
      반응형
      반응형

      npm 업데이트

      npm install -g npm


      npm 으로 설치한 글로벌 패키지 목록

      npm list -g --depth=0


      npm 으로 설치한 글로벌 패키지 업데이트

      npm update -g


      npm 으로 설치한 글로벌 패키지 삭제

      npm uninstall -g [패키지명]


      npm 최신 버전으로 업데이트

      npm install -g npm


      추후에.. 또 필요한게 있으면 추가 해야겠다...

      728x90
      반응형

      + Recent posts