[특강] 기술 전환점에서의 오픈소스와 개발자 - 래블업 신정규 대표님
특강 일정: 2023년 5월 15일 (월) 특강 장소: 국민대학교 미래관 611호 제목: 기술 전환점에서의 오픈소스와 개발자 발표자: 신정규 대표/연구원 (구글 Developers Experts, (주)래블업) 요약: 이 강연은 오픈소스 활동과 함께한 20년 동안 발표자가 경험한 다양한 삶의 이야기들과 함께, 소프트웨어 개발자들이 시대의 변화를 마주하는 방법에 대한 시각을 나눕니다. 한국에 몇 없는 구글 개발자인 신정규 대표님의 강연을 듣게 되어 영광이었습니다. 소중한 강연을 들을 기회를 마련해 주신 국민대학교 김상철 교수님께 감사드립니다. 강연을 통해 앞으로 프로그래머가 준비해야 할 기술들과 임해야 할 자세, 그리고 오픈소스의 기능과 중요성을 느끼게 해 준 특강이었습니다. 프로그래밍의 의미? 20세기 ..
2023.05.16
[특강]개발자는 코딩하는 사람이 아니다
위 링크 영상을 바탕으로 작성한 글입니다. "개발자라 한다면 스스로를 코딩하는 사람으로 정의하지 않았으면 좋겠다" "비즈니스 문제를 해결하는 사람으로 생각하는 것이 좋겠다." 배달의민족 김범준 대표의 좋은 개발자란 어떤 사람인지의 대해서 나오는 영상입니다. 엘리베이터를 기다리는 것이 지루하다는 문제가 있다고 생각해 봅시다. 사람들은 '엘리베이터가 늦게 오는 것 같다'라고 말합니다. 이에 대해 어떤 두 회사는 각각 다른 방법으로 문제를 해결합니다. A 회사는 많은 돈을 써서 엘리베이터 속도를 높이는 공사를 합니다. B 회사는 엘레베이터 앞에 거울을 설치합니다. A 회사는 엘리베이터가 실제로 느리다고 문제를 해석했고, B 회사는 엘리베이터를 기다리는 그 순간의 지루함을 문제로 해석하였습니다. 엘레베이터를 ..
2023.05.13
no image
[Spring]Github Actions로 Springboot CI 구현하기, postgres 설정
여기서 CI/CD란? CI/CD는 Continuous Integration(지속적 통합) / Continuous Delivery(지속적 전달)의 줄임말입니다. 애플리케이션 개발 단계를 자동화하여 애플리케이션을 더욱 짧은 주기로 배포할 수 있습니다. CI/CD는 새로운 코드 통합으로 인해 개발 및 운영팀에 발생하는 문제(일명 "통합 지옥(integration hell)")를 해결하기 위한 솔루션입니다. "CI"는 개발자를 위한 자동화 프로세스인 지속적인 통합(Continuous Integration)을 의미합니다. 지속적인 통합이 제대로 구현되면 애플리케이션 코드의 새로운 변경 사항이 정기적으로 빌드 및 테스트를 거쳐 공유 리포지토리에 병합됩니다. 따라서 여러 명의 개발자가 동시에 애플리케이션 개발과 관련..
2023.05.01
[기타] 옥상달빛 - 수고했어, 오늘도(Highlight) 기타 커버
Model: HEX-F300 Half-Down Tuning, 3 Capo Full sheet : https://youtu.be/gjyF8rJulWU
2023.04.18
no image
[Tip] YouTube Music for Mac 맥에서 유튜브 뮤직 사용하기
매번 브라우저로 유튜브 뮤직 탭을 들어가서 노래를 바꾸는 번거로움이 있어 App Store에 검색을 해보았지만... 지원하지 않는군요 그래서 없을까 해서 찾아보았는데 정식은 아니지만 App으로 사용할 수 있도록 개발하여 배포해 주시는 분이 있어 공유해 드립니다. 우선 URL 접속해 봅시다. https://github.com/steve228uk/YouTube-Music GitHub - steve228uk/YouTube-Music: A Mac app wrapper for music.youtube.com :musical_note: A Mac app wrapper for music.youtube.com - GitHub - steve228uk/YouTube-Music: A Mac app wrapper for mu..
2023.04.16
[개발 일기][Spring]Spring Security에서 AccessDeniedHandler 와AuthenticationEntryPoint
Spring Security는 유저에 대한 인증 및 권한처리를 가능하게 해주는 spring 보안 프레임워크입니다. 저는 프로젝트를 진행하면서 @RestControllerAdvice를 사용해 전역적으로 예외 처리를 하도록 하였으나, 기대한 HTTP status code와 에러 메시지와는 달리 403 Fobidden만 응답받을 뿐이었습니다. 이 문제는 User가 로그인을 하지 않은 채, 서비스의 접근할 경우 발생한 예외였습니다. 즉 인증되지 않은 클라이언트가 서버에 요청을 보냈을 때의 발생한 상황이었습니다. 조사해 보니 Spring Security의 Filter Chain으로 발생한 예외는 서블릿 필터 단계에 속하는 부분이기 때문에 @RestControllerAdvice와 같은 어노테이션으로 예외 처리를 ..
2023.04.14
no image
[무료]Launcher - 아이폰 잠금화면에 인스타그램 넣는법
클릭 시 인스타그램으로 바로 이동하는 잠금화면 위젯을 추가하는 법을 알려드리겠습니다. 먼저 App store에서 Launcher를 설치합니다. 앱을 실행한 후, Lock Screen Widget을 클릭합니다. App Launcher를 클릭합니다. instagram을 검색하고 맨 위에 instagram 앱을 클릭합니다. 기본 설정으로 한 후 오른쪽 위에 V를 클릭합니다. 잠금화면을 꾹 누른 후, 잠금 화면 수정 화면에서 위젯을 추가하는 버튼을 누릅니다. 그 후 Launcher 앱을 찾아서 클릭합니다. (없는 경우, 아이폰을 껐다 켜봅니다.) Tap to choose widget을 클릭합니다. Widget Choose를 클릭합니다. Instagram Widget이 생긴 것을 볼 수 있습니다. 끝입니다! 하지..
2023.04.11
[API]HTTP methods에서 Idempotency(멱등법칙)이란?
"In the context of REST APIs, when making multiple identical requests has the same effect as making a single request – then that REST API is called idempotent." Idempotency 수학에서 Idempotency(멱등법칙)이란, 아무리 연산을 여러 번 해도 결과 값이 달라지지 않는 법칙입니다. 예를 들어, 1 * 1 * 1 * 1 * 1 같은 연산입니다. REST API에서 Idempotency란 성공적으로 수행된 요청이 서버 리소스에 미치는 효과가 해당 요청이 몇 번 실행되었는지에 독립적인 것을 의미합니다. REST API를 설계할 때 API 소비자가 실수를 할 수 있다는 점을..
2023.04.10
  • 특강 일정: 2023년 5월 15일 (월)
  • 특강 장소: 국민대학교 미래관 611호
  • 제목: 기술 전환점에서의 오픈소스와 개발자 
  • 발표자: 신정규 대표/연구원 (구글 Developers Experts, (주)래블업)
  • 요약: 이 강연은 오픈소스 활동과 함께한 20년 동안 발표자가 경험한 다양한 삶의 이야기들과 함께, 소프트웨어 개발자들이 시대의 변화를 마주하는 방법에 대한 시각을 나눕니다.

한국에 몇 없는 구글 개발자인 신정규 대표님의 강연을 듣게 되어 영광이었습니다.

소중한 강연을 들을 기회를 마련해 주신 국민대학교 김상철 교수님께 감사드립니다.

강연을 통해 앞으로 프로그래머가 준비해야 할 기술들과 임해야 할 자세, 그리고 오픈소스의 기능과 중요성을 느끼게 해 준 특강이었습니다.

프로그래밍의 의미?

  • 20세기 컴퓨터에서 돌아가는 소프트웨어를 만드는 작업
  • 21세기 프로그래밍이 가능한 전자기기를 통한 유무형의 모든 창작 작업 

프로그래밍은 과거보다 더 넓은 의미를 갖게 되었습니다. 더 이상 컴퓨터에서만 돌아가는 소프트웨어가 아닌 모든 창작 작업을 프로그래밍의 의미로 볼 수 있습니다.

 

프로그래밍의 중요성 또한 커지고 있습니다.

세상은 무엇으로 이루어져 있는가 물어본다면, 대표적으로 정치, 경제, 사회, 문화, 기술, 과학라고 할 수 있습니다.

우리는 현재 기술과 과학이 중요한, 정치, 경제, 사회, 문화의 연결 고리를 프로그래밍이 하고있는 시대에 살고있다고 강조하셨습니다.

이를 통해 프로그래밍은 우리 일상에서 가까워지고 있고 중요하게 다가오고 있다는 것을 확인하였습니다.

 

“오픈소스 프로그래밍이라 쓰고 인생이라고 읽어봅시다.”

 

신정규 대표님은 '오픈소스’를 강조하셨습니다. 

경제적인 관점에서 희소성이 줄어들수록 가치가 떨어진다는 원리입니다.

그런데 본인의 코드가 멀리 퍼져 누구나 알게된 코드가 되었다고 상상해 봅시다.

그럼 저의 코드는 가치가 떨어졌을까요?

저는 아니라고 대답할 것 같습니다.

 

나만 알고 있는 코드는 내가 지우면 끝입니다. 어떤 문제가 있고, 더 좋은 방법이 있어도 내가 알지 못하면 알 수 없습니다. 하지만, 오픈소스로 코드를 남긴다면 기록으로 남게 됩니다. 그리고 많은 사람들과 함께 자신의 코드를 개선해갈 수 있어 발전 가능성이 매우 높아집니다. 

이는 저에게 향후 개발 프로젝트에 있어 오픈소스로 개발을 해야겠다는 영감을 주었습니다.

우리는 언제나 지나간 후의 그림자를 본다

지금 IT 트렌드 기술이라 하면,

ML/ AI, 오픈소스 하드웨어 플랫폼, 메타버스 '기반’ 기술, aI 기반 전문가 시스템, 머신 주도적 기술 / 과학

스마트 정치/ 경제 등이 있습니다. 지금 이 기술들을 공부하겠다고 내가 그 기술을 습득했을 때 미래는 어쩌면 또 다른 기술이 트렌드가 될 수 있습니다. 

그래서 앞으로의 흐름을 보기 위해 노력해야 한다고 느꼈습니다.

 

위 링크 영상을 바탕으로 작성한 글입니다.
 
"개발자라 한다면 스스로를 코딩하는 사람으로 정의하지 않았으면 좋겠다"
"비즈니스 문제를 해결하는 사람으로 생각하는 것이 좋겠다."
 
배달의민족 김범준 대표의 좋은 개발자란 어떤 사람인지의 대해서 나오는 영상입니다.
 
엘리베이터를 기다리는 것이 지루하다는 문제가 있다고 생각해 봅시다.
사람들은 '엘리베이터가 늦게 오는 것 같다'라고 말합니다.
 
이에 대해 어떤 두 회사는 각각 다른 방법으로 문제를 해결합니다.
A 회사는 많은 돈을 써서 엘리베이터 속도를 높이는 공사를 합니다.
B 회사는 엘레베이터 앞에 거울을 설치합니다.
 
A 회사는 엘리베이터가 실제로 느리다고 문제를 해석했고,
B 회사는 엘리베이터를 기다리는 그 순간의 지루함을 문제로 해석하였습니다.
엘레베이터를 기다리는 것이 지루하다는 문제를 어떻게 바라보느냐에 따라 해결법이 크게 달라집니다.
 
"풀고자 하는 문제를 정확히 이해하는 것, 여기에 노력의 80%는 들어가야 되지 않나"
 
어떠한 문제를 정확히 이해하는 것, 그 문제에 대해 해결법을 제시하는 것이
'개발자'다라고 영상에서 말합니다.
즉 '문제 해결력'이 중요하다는 것입니다.
 
내가 어떠한 일을 한 것이 얼마큼의 비즈니스적 가치가 있는가
코드를 1000줄, 10000줄을 썼다고 해서 그 가치를 증명하는 방법이 아닙니다.
어쩌면 코드 한 줄 안 썼어도 코드 10000줄짜리 일 보다 더 비즈니스적 가치를 지닐 수 있습니다.
 
하지만 본인의 해결법이 무조건 옳은 해결법이 아니겠죠
구성원과 '소통'하는 것도 중요합니다.
"엘리베이터가 늦게 오는 것 같아요? 그럼 거울을 설치하는건 어때요?"
"아니지 늦게 오니까 엘레베이터 속도를 빠르게 해야지"
어쩌면 더 좋은 해결법이 나올 수 있기 때문에 의견을 나누는 시간도 무척 중요합니다.
 
"SOFTWARE IS EATING THE WORLD"
 
세상의 문제들이 점점 소프트웨어로 해결할 수 있는 시대가 온 것 같습니다.
 
예를 들어, 배달의 민족 앱을 통해 배달이 안 되는 식당도 배달이 가능하게 되었고, 원하는 시간에 배달이 오도록 할 수 있고, 환경 문제도 해결할 수도 있는 등의 소비자가 겪을 수 있는 문제를 소프트웨어적으로 해결한 사례입니다.
 
일상에서, 사회적으로, 어디서든 어떤 문제를 발견하면 
이를 어떻게 해결할 것인가 고민하는 습관을 가져야겠다고 생각하였습니다.
그렇다면 자연스레 개발자가 되어있지 않을까요

여기서 CI/CD란?

CI/CD는 Continuous Integration(지속적 통합) / Continuous Delivery(지속적 전달)의 줄임말입니다.

애플리케이션 개발 단계를 자동화하여 애플리케이션을 더욱 짧은 주기로 배포할 수 있습니다.
CI/CD는 새로운 코드 통합으로 인해 개발 및 운영팀에 발생하는 문제(일명 "통합 지옥(integration hell)")를 해결하기 위한 솔루션입니다.

 

"CI"는 개발자를 위한 자동화 프로세스인 지속적인 통합(Continuous Integration)을 의미합니다.  지속적인 통합이 제대로 구현되면 애플리케이션 코드의 새로운 변경 사항이 정기적으로 빌드 및 테스트를 거쳐 공유 리포지토리에 병합됩니다. 따라서 여러 명의 개발자가 동시에 애플리케이션 개발과 관련된 코드 작업을 할 경우 서로 충돌하는 문제를 이 방법으로 해결할 수 있습니다.

 

"CD"는 지속적인 서비스 제공(Continuous Delivery) 및/또는 지속적인 배포(Continuous Deployment)를 의미하며 이 두 용어는 상호 교환하여 사용됩니다. 두 가지 의미 모두 파이프라인의 추가 단계에 대한 자동화를 뜻하지만 때로는 얼마나 많은 자동화가 이루어지고 있는지를 설명하기 위해 별도로 사용되기도 합니다. 지속적인 통합(CI)을 통해 만들어진 결과물을 자동화된 프로세스를 통해 릴리스 과정을 자동화하고, 사용자에게 빠르게 새로운 기능을 제공할 수 있습니다.

 

Github Actions

github에서 공식적으로 제공하는 CI / CD 툴(개발 워크 플로우 자동화 툴)이라고 보면 됩니다.

Actions탭을 클릭 후 New workflow를 클릭하면 다음과 같은 페이지로 이동합니다.

여러 프레임워크 및 언어를 위한

저는 Spring build tool로 Gradle을 사용하기 때문에 Java with Gradle을 사용하였습니다.

 

생성되는 파일과 Path는. github/workflows/gradle.yml입니다.

아래는 초기 설정입니다.

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

name: Java CI with Gradle

on:
  push:
    branches: [ "develop" ]
  pull_request:
    branches: [ "develop" ]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    - name: Build with Gradle
      uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
      with:
        arguments: build

 

 

졸업 프로젝트에서 사용한 gradle.yml입니다. 

name: SpringBoot CI with Gradle

on:
  push:
    branches:
      - '**'
      - '!master'
  pull_request:
    branches:
      - '**'
      - '!master'

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      working-directory: ./api
    defaults:
      run:
        working-directory: ${{ env.working-directory }}
    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_USER: 
          POSTGRES_PASSWORD: 
          POSTGRES_DB: 
          POSTGRES_HOST: localhost
          POSTGRES_PORT: 5432
        ports:
          - 5432:5432
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: "11"
          distribution: "temurin"

      - name: Cache gradle
        uses: actions/cache@v3
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build with Gradle
        run: ./gradlew clean build

      - name: Run Test
        run: ./gradlew test

      - name: Publish Test Results
        uses: EnricoMi/publish-unit-test-result-action@v2
        if: always()
        with:
          files: |
            api/build/test-results/**/*.xml

위에서부터 차근히 살펴보겠습니다.

 

name: Workflow의 이름을 나타냅니다.
on: Workflow가 실행되는 조건을 지정합니다. 위의 코드에서는 push 이벤트와 pull_request 이벤트가 발생했을 때, master 브랜치가 아닌 모든 브랜치에서 Workflow가 실행되도록 설정되어 있습니다.
jobs: 이 Workflow가 수행하는 작업을 정의합니다. 위의 코드에서는 build라는 이름의 작업이 정의되어 있습니다.
runs-on: 이 작업이 실행되는 환경을 지정합니다. 위의 코드에서는 ubuntu-latest 환경에서 실행되도록 설정되어 있습니다.
env: 이 작업에서 사용하는 환경 변수를 지정합니다. 위의 코드에서는 working-directory 변수를 지정하여 작업 디렉터리를 지정하고 있습니다.
services: 이 작업에서 사용하는 서비스를 지정합니다. 

postgres:

- image: 실행할 이미지를 지정합니다. 이 경우, PostgreSQL 14 버전 이미지인 postgres:14를 사용합니다.
-
 env: 컨테이너에서 사용할 환경 변수를 지정합니다. 
- POSTGRES_USER: 데이터베이스의 사용자 이름
- POSTGRES_PASSWORD: 사용자의 비밀번호
- POSTGRES_DB: 데이터베이스의 이름
- POSTGRES_HOST: 호스트 이름
- POSTGRES_PORT: 포트 번호
- ports: 컨테이너와 호스트 간의 포트 포워딩을 설정합니다. 이 경우, PostgreSQL 데이터베이스에서 사용하는 기본 포트인 5432를 호스트의 5432 포트와 연결합니다.
- options: 컨테이너를 실행할 때 추가적인 옵션을 설정합니다. 이 경우, PostgreSQL 데이터베이스가 실행되는 동안 컨테이너 상태를 모니터링하기 위한 옵션을 설정합니다.
--health-cmd pg_isready: pg_isready 명령을 사용하여 PostgreSQL 데이터베이스의 상태를 모니터링합니다.
--health-interval 10s: pg_isready 명령을 실행하는 주기를 10초로 설정합니다.
--health-timeout 5s: pg_isready 명령이 실행되는 최대 시간을 5초로 설정합니다.
--health-retries 5: pg_isready 명령을 재시도할 횟수를 5회로 설정합니다.

 

steps: 이 작업에서 수행하는 일련의 단계를 정의합니다. 위의 코드에서는 아래와 같은 단계가 수행됩니다.
actions/checkout@v3 단계: Git 저장소에서 코드를 체크아웃합니다.
actions/setup-java@v3 단계: JDK 11을 설치하고 환경 변수를 설정합니다.
actions/cache@v3 단계: Gradle 캐시를 저장하고 복원합니다.

  • uses: 이 액션에서 사용할 GitHub Actions를 지정합니다. 이 경우, actions/cache@v3를 사용하고 있습니다.
  • with: 이 액션에서 사용할 입력값을 지정합니다. 여기서는 path, key, restore-keys를 사용하고 있습니다.
    • path: 캐시로 사용할 파일 또는 디렉토리를 지정합니다. 이 경우, Gradle 캐시 파일이 저장된 경로인 ~/.gradle/caches와 ~/.gradle/wrapper를 지정합니다.
    • key: 캐시의 고유 키를 지정합니다. 이 키는 캐시를 검색하거나 저장할 때 사용됩니다. 여기서는 러너의 운영 체제(${{ runner.os }})와 Gradle 설정 파일의 해시값($hashFiles('**/*.gradle*', '**/gradle-wrapper.properties'))을 조합하여 고유 키를 생성합니다.
    • restore-keys: 캐시를 검색할 때 사용할 키를 지정합니다. 이 경우, 러너의 운영 체제(${{ runner.os }})와 "gradle"을 조합하여 키를 생성합니다.

 

./gradlew clean build: Gradle 빌드를 실행합니다.

./gradlew test: Gradle 테스트를 실행합니다.

EnricoMi/publish-unit-test-result-action@v2 단계: 테스트 결과를 게시합니다.

여기서 EnricoMi는 자동화된 테스트 실행 후, 테스트 결과를 깃허브에 게시하는 기능을 수행합니다.

자세한 내용은 아래 github에서 확인하실 수 있습니다.

https://github.com/EnricoMi/publish-unit-test-result-action

 

Actions에서 동작하는 모습

 

 

참고 자료:

https://hwasurr.io/git-github/github-actions/

 

Github Actions를 이용해 CI/CD 파이프라인 구성하기

Github Actions를 통해 코드 변경사항 반영에 따라 진행되는 workflow를 자동화하는 과정에 대해 기록합니다.

hwasurr.io

https://velog.io/@sontulip/github-actions-ci

 

Github Actions를 이용해 CI 구성하기 (Java, Gradle, Jacoco)

소개 Github Actions는 Github에서 제공하는 CI/CD 툴입니다. Github이 서버를 제공해주기 때문에 따로 CI/CD를 위한 서버를 구성해주지 않아도 되어 부담이 적고 간편하게 설정할 수 있다는 장점이 있습니

velog.io

https://www.redhat.com/ko/topics/devops/what-is-ci-cd

 

Model: HEX-F300
Half-Down Tuning, 3 Capo
Full sheet : https://youtu.be/gjyF8rJulWU

매번 브라우저로 유튜브 뮤직 탭을 들어가서 노래를 바꾸는 번거로움이 있어
App Store에 검색을 해보았지만... 지원하지 않는군요

그래서 없을까 해서 찾아보았는데 
정식은 아니지만 App으로 사용할 수 있도록 개발하여 배포해 주시는 분이 있어 공유해 드립니다.
 
우선 URL 접속해 봅시다.
https://github.com/steve228uk/YouTube-Music

 

GitHub - steve228uk/YouTube-Music: A Mac app wrapper for music.youtube.com

:musical_note: A Mac app wrapper for music.youtube.com - GitHub - steve228uk/YouTube-Music: A Mac app wrapper for music.youtube.com

github.com

설치 방법은 아래와 같이 두 방법이 있습니다.
직접 파일을 다운로드하여 설치하거나, 
Homebrew로 터미널에서 커맨드를 입력하여 설치하는 방법입니다.

brew install --cask yt-music

Homebrew로 설치하려는 분들은 위 커맨드를 터미널에 입력하시면 됩니다.
 
직접 Link로 들어가 설치하시려는 분들은 Download Latest Version을 클릭하면 다음 화면으로 연결됩니다.

YT-Music-1.x.x.zip을 다운로드하고 실행시키시면 됩니다.
 
실행시키신 후 youtube music 계정 로그인 하시면 끝입니다.
 
알림을 허용하시면 이런 식으로 현재 재생되고 있는 음악이 표시됩니다.

 
다음 노래도 알림으로 알려주어서 편리합니다.

원래는 safari -> youtube music tab을 했어야했는데
이제는 yotubue music 앱 바로 접속할 수 있어서 과정 하나가 적어져 효율적이군요!

 

Spring Security는 유저에 대한 인증 및 권한처리를 가능하게 해주는 spring 보안 프레임워크입니다.

 

저는 프로젝트를 진행하면서 @RestControllerAdvice를 사용해

전역적으로 예외 처리를 하도록 하였으나, 기대한 HTTP status code와 에러 메시지와는 달리

403 Fobidden만 응답받을 뿐이었습니다.

이 문제는 User가 로그인을 하지 않은 채, 서비스의 접근할 경우 

발생한 예외였습니다. 즉 인증되지 않은 클라이언트가 서버에 요청을 보냈을 때의 발생한 상황이었습니다.

 

조사해 보니 Spring Security의 Filter Chain으로 발생한 예외는 서블릿 필터 단계에 속하는 부분이기 때문에 @RestControllerAdvice와 같은 어노테이션으로 예외 처리를 불가능하다는 사실을 알았습니다.

그래서 Spring Security가 발생시키는 Exception Handler를 따로 구현해야 할 필요가 있었습니다.

 

Spring Security에선 AccessDeniedHandler interface와 AuthenticationEntryPoint interface가 존재합니다.

AccessDeniedHandler는 서버에 요청을 할 때 액세스가 가능한지 권한을 체크후 액세스 할 수 없는 요청을 했을 시 동작되고,

AuthenticationEntryPoint는 인증이 되지않은 유저가 요청을 했을 때 동작됩니다.

제가 참여한 프로젝트에선 User의 권한보다 인증의 비중이 더 높아, AuthenticationEntryPoint만 따로 구현해주었습니다.

package com.thesurvey.api.exception;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

/**
 * Handles authentication errors that occur during the Spring Security filter chain, such as when a
 * user attempts to access a secured endpoint without authentication credentials.
 */
public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint {

    // method is called by the Spring Security filter chain when an authentication error occurs.
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("text/plain;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("권한이 없습니다.");
    }
}

 

public class SecurityConfiguration {

    private final AuthenticationProvider authenticationProvider;

    private final SessionFilter sessionFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        return http
            .csrf().disable()
            .cors().and()
            .authorizeRequests()
                .antMatchers(
                    "/v2/api-docs/**",
                    "/v3/api-docs/**",
                    "/configuration/**",
                    "/swagger-ui.html",
                    "/swagger-ui/**",
                    "/docs/**"
                ).permitAll()
                .antMatchers("/admin/**").hasAuthority("ADMIN")
                .antMatchers("/surveys/**").authenticated()
                .antMatchers("/users/**").authenticated()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().permitAll()
            .and()
            .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPointHandler())
            .and()
            ...

 

AuthenticationEntryPoint interface를 구현한 AuthenticationEntryPointHandler 클래스를 만들고

.exceptionHandling()에 .authenticationEntryPoint(new AuthenticationEntryPointHandler())를 추가해 주었습니다.

 

참고 자료

https://velog.io/@park2348190/Spring-Security의-Unauthorized-Forbidden-처리

 

Spring Security의 Unauthorized, Forbidden 처리

Spring Security를 적용해서 HTTP 요청에 대해 인증 및 인가를 적용할 경우 시큐리티 필터 체인에 의해 인증 여부나 인가 여부에 따라 요청이 수락되거나 거절된다. 그런데 필터 체인 특성상 이런 Sprin

velog.io

https://kim-jong-hyun.tistory.com/m/36

클릭 시 인스타그램으로 바로 이동하는 잠금화면 위젯을 추가하는 법을 알려드리겠습니다.

 

먼저 App store에서 Launcher를 설치합니다.

앱을 실행한 후, Lock Screen Widget을 클릭합니다.

App Launcher를 클릭합니다.

instagram을 검색하고 맨 위에 instagram 앱을 클릭합니다.

기본 설정으로 한 후 오른쪽 위에 V를 클릭합니다.

잠금화면을 꾹 누른 후, 잠금 화면 수정 화면에서

위젯을 추가하는 버튼을 누릅니다.

그 후 Launcher 앱을 찾아서 클릭합니다. (없는 경우, 아이폰을 껐다 켜봅니다.)

Tap to choose widget을 클릭합니다.

Widget Choose를 클릭합니다.

Instagram Widget이 생긴 것을 볼 수 있습니다.

끝입니다!

하지만 위젯을 더 추가하려면 결제를 해야하기 때문에, 다른 유사한 앱을 사용해보시는 것도 추천드립니다.

<- Themify   /   Brass ->

 

"In the context of REST APIs, when making multiple identical requests has the same effect as making a single request – then that REST API is called idempotent."

Idempotency

수학에서  Idempotency(멱등법칙)이란, 아무리 연산을 여러 번 해도 결과 값이 달라지지 않는 법칙입니다.

예를 들어, 1 * 1 * 1 * 1 * 1 같은 연산입니다.

 

REST API에서 Idempotency란 성공적으로 수행된 요청이 서버 리소스에 미치는 효과가 해당 요청이 몇 번 실행되었는지에 독립적인 것을 의미합니다.

REST API를 설계할 때 API 소비자가 실수를 할 수 있다는 점을 인식해야 합니다. 클라이언트는 API에 중복 요청을 전송할 수 있습니다. API를 구현할 때 중복 요청이 시스템을 불안정하게 만들지 않도록 해야 합니다.

또한, Idempotency는 효율적인 캐싱 및 최적화 전략을 위한 주요 요소입니다. 캐시 및 콘텐츠 전송 네트워크(CDN)는 멱등한 요청의 결과를 저장하고 제공함으로써 서버 부하를 줄이고 응답 시간을 개선할 수 있습니다.

Example

예를 들어 HTTP 메소드들 중에서 DELETE 요청은
N개의 유사한 DELETE 요청을 실행할 때 첫 번째 요청은 리소스를 삭제하고 응답은 200(OK) 또는 204(No Content)가 될 것입니다.

나머지 N-1개의 요청은 404(찾을 수 없음)를 반환할 것입니다.

분명히 응답은 첫 번째 요청과 다르지만, 서버 측에서는 원본 리소스가 이미 삭제되었으므로 어떤 리소스의 상태 변경도 없습니다.

그러므로 DELETE 요청은 Idempotency 합니다.

HTTP methods supported Idempotency

(여기서 is safe란, 서버의 상태를 수정하지 않는 HTTP 방법은 안전한 방법을 의미합니다.)

참고 자료

https://restfulapi.net/idempotent-rest-apis/

 

Idempotency - What is an Idempotent REST API?

A REST API is called idempotent when making multiple identical requests to an API has the same effect as making a single request.

restfulapi.net

https://medium.com/nerd-for-tech/what-is-idempotency-in-rest-apis-and-why-should-you-care-8c0a55 0 e345 f