ALL
-
CORS란? CORS (Cross-Origin Resource Sharing) Policy(정책)는 웹 브라우저에서 실행되는 웹 애플리케이션들이 다른 도메인(origin)에 있는 리소스에 접근할 수 있는 권한을 부여하거나 제한하는 보안 정책입니다. 위 에러는 CORS 에러 입니다. 아마 다들 한 번 쯤은 봤을 에러인데요. 이 글에서는 왜 이러한 에러가 발생하는지, 그리고 어떻게 해결하는 지에 대해 아주아주 간략하게 정리해 보겠습니다. CORS에 대한 개념을 알아보기 위해 이 글을 보시는 것은 추천드리지 않습니다 🥲 다소 생략된 부분이 있다고 느끼실 수 있어요! CORS에러가 발생하는 이유 앞서 말했듯이 CORS는 다른 도메인에 있는 리소스에 접근하는 것과 관련이 있습니다. 여기서 다른 도메인(origin..
[React][Axios] CORS에러 발생 이유와 proxy를 통한 해결CORS란? CORS (Cross-Origin Resource Sharing) Policy(정책)는 웹 브라우저에서 실행되는 웹 애플리케이션들이 다른 도메인(origin)에 있는 리소스에 접근할 수 있는 권한을 부여하거나 제한하는 보안 정책입니다. 위 에러는 CORS 에러 입니다. 아마 다들 한 번 쯤은 봤을 에러인데요. 이 글에서는 왜 이러한 에러가 발생하는지, 그리고 어떻게 해결하는 지에 대해 아주아주 간략하게 정리해 보겠습니다. CORS에 대한 개념을 알아보기 위해 이 글을 보시는 것은 추천드리지 않습니다 🥲 다소 생략된 부분이 있다고 느끼실 수 있어요! CORS에러가 발생하는 이유 앞서 말했듯이 CORS는 다른 도메인에 있는 리소스에 접근하는 것과 관련이 있습니다. 여기서 다른 도메인(origin..
2023.10.16 -
배경 https://firebase.google.com/docs/auth/android/github-auth?hl=ko Android에서 GitHub를 사용하여 인증하기 | Firebase Authentication Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Android에서 GitHub를 사용하여 인증하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분 firebase.google.com 위 문서를 참고하여 깃허브 oauth 로그인을 구현하고자 하는데 제 애플리케이션에 SHA-1 등록을 하지 않아서 방법을 찾아보고 있었습니다 . . . 잘 알려진 방법인 터미널에 ./gradlew signingReport 를 입력하는 방법..
[AndroidStudio][FireBase] SHA-1 디지털 지문 발급받기 / zsh: permission denied: ./gradlew 해결배경 https://firebase.google.com/docs/auth/android/github-auth?hl=ko Android에서 GitHub를 사용하여 인증하기 | Firebase Authentication Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Android에서 GitHub를 사용하여 인증하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분 firebase.google.com 위 문서를 참고하여 깃허브 oauth 로그인을 구현하고자 하는데 제 애플리케이션에 SHA-1 등록을 하지 않아서 방법을 찾아보고 있었습니다 . . . 잘 알려진 방법인 터미널에 ./gradlew signingReport 를 입력하는 방법..
2023.10.16 -
localStorage와 sessionStorage 로컬 스토리지와 세션 스토리지는 자바 스크립트에서 사용되는 웹 스토리지 옵션입니다. 이 두 가지 기능은 웹 브라우저에서 키와 값으로 이루어진 데이터를 저장하는 데에 사용됩니다. 쿠키와의 차이점 웹 브라우저에 데이터를 저장하는 것이 쿠키와 유사하다고 생각할 수 있지만 다음과 같은 차이점이 존재합니다. 쿠키와 달리 네트워크 요청 시 서버로 전송되지 않는다 개발자가 브라우저 내 웹 스토리지 구성 방식을 설정할 수 있다 쿠키와 달리 HTTP 헤더를 통해 객체를 조작할 수 없다 프로토콜과 서브 도메인이 다르면 데이터에 접근할 수 없다 제공하는 프로퍼티와 메서드 공통 프로퍼티 localStorage.length 및 sessionStorage.length: 스토리지..
[JavaScript] Window.lacalStorage와 Window.sessionStoragelocalStorage와 sessionStorage 로컬 스토리지와 세션 스토리지는 자바 스크립트에서 사용되는 웹 스토리지 옵션입니다. 이 두 가지 기능은 웹 브라우저에서 키와 값으로 이루어진 데이터를 저장하는 데에 사용됩니다. 쿠키와의 차이점 웹 브라우저에 데이터를 저장하는 것이 쿠키와 유사하다고 생각할 수 있지만 다음과 같은 차이점이 존재합니다. 쿠키와 달리 네트워크 요청 시 서버로 전송되지 않는다 개발자가 브라우저 내 웹 스토리지 구성 방식을 설정할 수 있다 쿠키와 달리 HTTP 헤더를 통해 객체를 조작할 수 없다 프로토콜과 서브 도메인이 다르면 데이터에 접근할 수 없다 제공하는 프로퍼티와 메서드 공통 프로퍼티 localStorage.length 및 sessionStorage.length: 스토리지..
2023.10.01 -
파비콘은 웹페이지 아이콘이라고 생각하면 됩니다. 크롬의 경우 북마크를 했을 때 웹페이지의 아이콘과 웹페이지 이름이 같이 보이는데, 이 아이콘을 파비콘이라고 합니다. 프로젝트를 만들 때 파비콘을 설정해야 안심이 되더라고요... 그냥 지구 모양은 절대 못봐줌 그래서!! 저도 할 때마다 맨날 어떻게 하는지 까먹는 파비콘 등록하기에 대해 포스팅을 합니다. ico 이미지 준비 파비콘 아이콘의 확장자는 ico가 적합합니다. https://www.hipdf.com/kr/png-to-ico PNG를 ICO로 변환 - PNG에서 아이콘 생성하기 - HiPDF PNG에서 빠르게 아이콘 파일을 생성합니다. 16x16에서 256x256까지 아이콘 사이즈 지정이 가능합니다. 설치 또는 가입이 필요하지 않습니다. PNG를 ICO..
[HTML] 웹페이지 파비콘 등록하기파비콘은 웹페이지 아이콘이라고 생각하면 됩니다. 크롬의 경우 북마크를 했을 때 웹페이지의 아이콘과 웹페이지 이름이 같이 보이는데, 이 아이콘을 파비콘이라고 합니다. 프로젝트를 만들 때 파비콘을 설정해야 안심이 되더라고요... 그냥 지구 모양은 절대 못봐줌 그래서!! 저도 할 때마다 맨날 어떻게 하는지 까먹는 파비콘 등록하기에 대해 포스팅을 합니다. ico 이미지 준비 파비콘 아이콘의 확장자는 ico가 적합합니다. https://www.hipdf.com/kr/png-to-ico PNG를 ICO로 변환 - PNG에서 아이콘 생성하기 - HiPDF PNG에서 빠르게 아이콘 파일을 생성합니다. 16x16에서 256x256까지 아이콘 사이즈 지정이 가능합니다. 설치 또는 가입이 필요하지 않습니다. PNG를 ICO..
2023.09.09 -
RestTemplate RestTemplate는 스프링 프레임워크가 제공하는 클래스로, RESTful 웹 서비스와 상호작용 하는 과정을 단순화하여 편리하게 API를 호출할 수 있습니다. RestTemplate의 동작 원리 어플리케이션이 RestTemplate를 생성합니다. (URI, HTTP 메서드 등 헤더를 담아서 요청함) RestTemplaterk HttpMessageConverter를 사용하여 requestEntity를 요청 메세지로 변환합니다. RestTemplate가 ClientHttpRequestFactory로 부터 ClientHttpRequest를 가져와서 요청을 보냅니다. ClientHttpRequest는 요청 메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신합니다. RestTempla..
[Spring] Rest Template란?RestTemplate RestTemplate는 스프링 프레임워크가 제공하는 클래스로, RESTful 웹 서비스와 상호작용 하는 과정을 단순화하여 편리하게 API를 호출할 수 있습니다. RestTemplate의 동작 원리 어플리케이션이 RestTemplate를 생성합니다. (URI, HTTP 메서드 등 헤더를 담아서 요청함) RestTemplaterk HttpMessageConverter를 사용하여 requestEntity를 요청 메세지로 변환합니다. RestTemplate가 ClientHttpRequestFactory로 부터 ClientHttpRequest를 가져와서 요청을 보냅니다. ClientHttpRequest는 요청 메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신합니다. RestTempla..
2023.09.09 -
OAuth 앱 등록하기 깃허브에서 Setting > Developer Setting > OAuth Apps > Register a new application 으로 이동하여 OAuth 로그인을 할 앱을 등록해줍니다. 저는 현재 서버를 배포하지 않고 로컬에서 작업하고 있기 때문에 Hompage URL은 http://localhost:8080으로 해줬습니다. Authorization callback URL에는 로그인 후 돌아갈 즉 redirect url을 입력해주세요 토큰 생성하기 Register application을 누르고 바로 다음 화면에서 Generate a new client secret을 클릭하면 토큰이 발급됩니다. 발급받은 토큰은 Spring에서 사용되니 어딘가에 복사 해놓으세요 Spring 설..
[Spring] Spring에서 깃허브 OAuth 로그인하기OAuth 앱 등록하기 깃허브에서 Setting > Developer Setting > OAuth Apps > Register a new application 으로 이동하여 OAuth 로그인을 할 앱을 등록해줍니다. 저는 현재 서버를 배포하지 않고 로컬에서 작업하고 있기 때문에 Hompage URL은 http://localhost:8080으로 해줬습니다. Authorization callback URL에는 로그인 후 돌아갈 즉 redirect url을 입력해주세요 토큰 생성하기 Register application을 누르고 바로 다음 화면에서 Generate a new client secret을 클릭하면 토큰이 발급됩니다. 발급받은 토큰은 Spring에서 사용되니 어딘가에 복사 해놓으세요 Spring 설..
2023.09.01 -
인텐트란 하나의 액티비티에서 다른 액티비티로 전환하기 위한 도구입니다. 인텐트를 사용하여 다른 액티비티에 전달해야 하는 값을 넘겨줄 수도 있습니다. 인텐트는 크게 명시적 인텐트와 암시적 인텐트가 있습니다. 명시적 인텐트 명시적 인텐는 어떤 액티비티로 넘어갈지 명확하게 아는 상태에서 사용합니다. 예를들어 MainActivity에서 버튼을 누르면 TargetActivity로 넘어가는 상황에서, 버튼을 누르면 무조건 TargetActivity 로 넘어가기 때문에 명시적 인텐트를 사용합니다. val intent = Intent(this, TargetActivity::class.java) startActivity(intent) Intent의 첫 번째 인자는 context, 두 번째 인자는 클래스 파일 입니다. s..
[Android Studio] 인텐트 알아보기인텐트란 하나의 액티비티에서 다른 액티비티로 전환하기 위한 도구입니다. 인텐트를 사용하여 다른 액티비티에 전달해야 하는 값을 넘겨줄 수도 있습니다. 인텐트는 크게 명시적 인텐트와 암시적 인텐트가 있습니다. 명시적 인텐트 명시적 인텐는 어떤 액티비티로 넘어갈지 명확하게 아는 상태에서 사용합니다. 예를들어 MainActivity에서 버튼을 누르면 TargetActivity로 넘어가는 상황에서, 버튼을 누르면 무조건 TargetActivity 로 넘어가기 때문에 명시적 인텐트를 사용합니다. val intent = Intent(this, TargetActivity::class.java) startActivity(intent) Intent의 첫 번째 인자는 context, 두 번째 인자는 클래스 파일 입니다. s..
2023.08.30 -
@OneToMany @OneToMany 어노테이션은 하나의 엔티티와 다른 엔티티간의 일대다 관계를 매핑하는데 사용됩니다. 일대다 관계에서는 하나의 인스턴스가 다른 엔티티의 여러 인스턴스와 연결됩니다. @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "department", cascade = CascadeType.ALL) private List employees = new ArrayList(); } @Entity public class Employee { @Id @GeneratedValue..
[SpringBoot] @OneToMany, @ManyToOne, @ManyToMany 연관 관계 매핑, @JoinTable@OneToMany @OneToMany 어노테이션은 하나의 엔티티와 다른 엔티티간의 일대다 관계를 매핑하는데 사용됩니다. 일대다 관계에서는 하나의 인스턴스가 다른 엔티티의 여러 인스턴스와 연결됩니다. @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "department", cascade = CascadeType.ALL) private List employees = new ArrayList(); } @Entity public class Employee { @Id @GeneratedValue..
2023.08.30 -
스프링 시큐리티란? Spring Security는 자바 기반 웹 애플리케이션을 위한 보안 서비스를 제공합니다. Spring의 보안을 위한 표준 라이브러리로 사용됩니다. 스프링 시큐리티가 제공하는 기능은 다음과 같습니다. 인메모리 사용자 하나를 포함하는 AuthenticationManager 빈 사용자 이름은 user이고 암호는 콘솔에 출력됩니다 /css 나 /image 같은 공용 정적 리소스 위치를 위해 무시되는 경로, 다른 모든 엔드포인트에 대한 HTTP 기본 인증 스프링의 ApplicationEventPublisher 인터페이스로 게시되는 스프링 이벤트 자동 생성되는 기본 로그인 페이지 사용 예시 @Configuration @EnableWebSecurity public class SecurityCon..
[SpringBoot]스프링 시큐리티란? (Spring Security)스프링 시큐리티란? Spring Security는 자바 기반 웹 애플리케이션을 위한 보안 서비스를 제공합니다. Spring의 보안을 위한 표준 라이브러리로 사용됩니다. 스프링 시큐리티가 제공하는 기능은 다음과 같습니다. 인메모리 사용자 하나를 포함하는 AuthenticationManager 빈 사용자 이름은 user이고 암호는 콘솔에 출력됩니다 /css 나 /image 같은 공용 정적 리소스 위치를 위해 무시되는 경로, 다른 모든 엔드포인트에 대한 HTTP 기본 인증 스프링의 ApplicationEventPublisher 인터페이스로 게시되는 스프링 이벤트 자동 생성되는 기본 로그인 페이지 사용 예시 @Configuration @EnableWebSecurity public class SecurityCon..
2023.08.23 -
롬복이란? 롬복은 자바에서 클래스를 작성을 간결하게 할 수 있도록 어노테이션(annotations)을 이용하여 자동으로 Getter, Setter, Constructor 등의 메서드를 생성하는 라이브러리 입니다. 롬복은 컴파일 과정에서 어노테이션을 통해 메서드를 생성합니다. 다양한 사용 예시 @Getter와 @Setter 필드의 게터와 세터를 생성합니다. import lombok.Getter; import lombok.Setter; @Getter @Setter public class Person { private String name; private int age; } @ToString 클래스의 toString 메서드를 생성합니다. import lombok.ToString; @ToString public..
[Java] Lombok 제대로 알아보기롬복이란? 롬복은 자바에서 클래스를 작성을 간결하게 할 수 있도록 어노테이션(annotations)을 이용하여 자동으로 Getter, Setter, Constructor 등의 메서드를 생성하는 라이브러리 입니다. 롬복은 컴파일 과정에서 어노테이션을 통해 메서드를 생성합니다. 다양한 사용 예시 @Getter와 @Setter 필드의 게터와 세터를 생성합니다. import lombok.Getter; import lombok.Setter; @Getter @Setter public class Person { private String name; private int age; } @ToString 클래스의 toString 메서드를 생성합니다. import lombok.ToString; @ToString public..
2023.08.22 -
https://docs.github.com/ko/rest?apiVersion=2022-11-28 GitHub REST API 설명서 - GitHub Docs 통합을 만들고, 데이터를 검색하고, 워크플로를 자동화하고, GitHub REST API를 사용하여 빌드합니다. docs.github.com 통합을 만들고, 데이터를 검색하고, 워크플로를 자동화하고, GitHub REST API를 사용하여 빌드합니다. docs.github.com](https://docs.github.com/ko/rest?apiVersion=2022-11-28) Java에서 GitHub REST API를 사용하는 방법에 대해 정리해봤습니다. 깃허브 API 말고도 다른 API에 요청을 보낼 때에도 응용할 수 있습니다. 의존성 추가 먼저 ..
[Java] 자바에서 GitHub REST API 사용하기https://docs.github.com/ko/rest?apiVersion=2022-11-28 GitHub REST API 설명서 - GitHub Docs 통합을 만들고, 데이터를 검색하고, 워크플로를 자동화하고, GitHub REST API를 사용하여 빌드합니다. docs.github.com 통합을 만들고, 데이터를 검색하고, 워크플로를 자동화하고, GitHub REST API를 사용하여 빌드합니다. docs.github.com](https://docs.github.com/ko/rest?apiVersion=2022-11-28) Java에서 GitHub REST API를 사용하는 방법에 대해 정리해봤습니다. 깃허브 API 말고도 다른 API에 요청을 보낼 때에도 응용할 수 있습니다. 의존성 추가 먼저 ..
2023.08.21 -
프로젝트를 하면서 Github API를 사용하게 되었는데, 사용하는 방법을 소개해 드리도록 하겠습니다! 의존성 추가하기 https://mvnrepository.com/artifact/org.kohsuke/github-api 먼저 위 문서에서 Project Documentation - Project Information - Dependencies 에 들어가 API를 사용할 수 있도록 의존성을 추가하겠습니다. 가장 최근 버전을 선택하고 자신의 프로젝트와 맞게 선택한 후 의존성을 추가해주세요 implementation group: 'org.kohsuke', name: 'github-api', version: '1.315' 저는 gradle을 사용하기 때문에 위 코드를 dependencies에 추가했습니다. 사..
[Java] Github API 사용하기프로젝트를 하면서 Github API를 사용하게 되었는데, 사용하는 방법을 소개해 드리도록 하겠습니다! 의존성 추가하기 https://mvnrepository.com/artifact/org.kohsuke/github-api 먼저 위 문서에서 Project Documentation - Project Information - Dependencies 에 들어가 API를 사용할 수 있도록 의존성을 추가하겠습니다. 가장 최근 버전을 선택하고 자신의 프로젝트와 맞게 선택한 후 의존성을 추가해주세요 implementation group: 'org.kohsuke', name: 'github-api', version: '1.315' 저는 gradle을 사용하기 때문에 위 코드를 dependencies에 추가했습니다. 사..
2023.08.20 -
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. 위와 같은 에러 메세지를 받게 되어 --warning-mode all을 없애보고자 합니다. 먼저 Settings - Build, Execution, Deployment - Build Tools, Gradle에서 Build and run using과 Run tests using을 gradle에서 int..
[IntelliJ][Gradle] 빌드할 때 warning mode all 추가하기, You can use '--warning-mode all' ...Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. 위와 같은 에러 메세지를 받게 되어 --warning-mode all을 없애보고자 합니다. 먼저 Settings - Build, Execution, Deployment - Build Tools, Gradle에서 Build and run using과 Run tests using을 gradle에서 int..
2023.08.19 -
문제 상황 롬복을 사용하여 어노테이션(@Getter)으로 Getter를 만들고자 했는데, 막상 Getter가 만들어지지 않았습니다. 롬복을 사용한 다른 것에서도 똑같은 일이 발생하여 롭목 해결 방법 세 가지 해결 방법을 알려드리겠습니다. build.gradle dependencies { ... compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' ... } build.gradle 파일에 위 코드를 추가해주세요 플러그인 설치 Plugins에서 Lombok이 설치되었는지 확인해주세요 설정 변경 File - Setting..
[IntelliJ] lombok 인식 안 됨 해결 방법문제 상황 롬복을 사용하여 어노테이션(@Getter)으로 Getter를 만들고자 했는데, 막상 Getter가 만들어지지 않았습니다. 롬복을 사용한 다른 것에서도 똑같은 일이 발생하여 롭목 해결 방법 세 가지 해결 방법을 알려드리겠습니다. build.gradle dependencies { ... compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' ... } build.gradle 파일에 위 코드를 추가해주세요 플러그인 설치 Plugins에서 Lombok이 설치되었는지 확인해주세요 설정 변경 File - Setting..
2023.08.18 -
저는 지금 intelliJ Ultimate를 사용하고 있으나, 아마 Community 버전에서도 같은 방법으로 하셨을 때 문제 없으실 겁니다! 빌드 시스템이 Gradle일 때와, IntelliJ일 때의 방법이 다르니 참고하여 진행하세요 (개인적으로 전자의 방법을 추천드립니다.) 빌드 시스템이 Gradle일 때 프로젝트 생성하기 위와 같이 프로젝트를 생성합니다. build.gradle 에 의존성 추가하기 dependencies { ... implementation 'mysql:mysql-connector-java:8.0.33' ... } 위 코드를 build.gradle 파일에 추가하고 업데이트한 내용으로 다시 빌드합니다. 사용 예제 Main.java package org.example; import ja..
[IntelliJ] 인텔리제이에서 MySQL 연동하는 방법저는 지금 intelliJ Ultimate를 사용하고 있으나, 아마 Community 버전에서도 같은 방법으로 하셨을 때 문제 없으실 겁니다! 빌드 시스템이 Gradle일 때와, IntelliJ일 때의 방법이 다르니 참고하여 진행하세요 (개인적으로 전자의 방법을 추천드립니다.) 빌드 시스템이 Gradle일 때 프로젝트 생성하기 위와 같이 프로젝트를 생성합니다. build.gradle 에 의존성 추가하기 dependencies { ... implementation 'mysql:mysql-connector-java:8.0.33' ... } 위 코드를 build.gradle 파일에 추가하고 업데이트한 내용으로 다시 빌드합니다. 사용 예제 Main.java package org.example; import ja..
2023.08.17 -
기초적인 git 명령어 git init .git 파일을 생성하여 깃으로 관리할 수 있도록 하는 작업 .git파일이 없고 git init이 안 된 상태에서는 버전관리를 할 수 없음 git clone 리포지토리URL 원격 저장소의 리포지토리를 로컬 저장소로 가져오기 git remote origin main 리포지토리URL 로컬 저장소와 원격 저장소 연동하기 git remote -v remote된 원격 저장소 확인하기 git add . git add -A 현재 로컬에 모든 변경사항을 스테이징 하기(커밋을 할 수 있는 상태로 바꾸기) git add 파일경로 파일 경로에 있는 변경사항을 스테이징 하기(커밋을 할 수 있는 상태로 바꾸기 git commit -m "커밋 메세지" 스테이징 된 변경 사항들을 커밋하기 g..
[Git] git init부터 push까지, 로컬 저장소와 원격 저장소 연결하기, init, remote, status, branch, add, commit, push 등 기본적인 명령어 알아보기기초적인 git 명령어 git init .git 파일을 생성하여 깃으로 관리할 수 있도록 하는 작업 .git파일이 없고 git init이 안 된 상태에서는 버전관리를 할 수 없음 git clone 리포지토리URL 원격 저장소의 리포지토리를 로컬 저장소로 가져오기 git remote origin main 리포지토리URL 로컬 저장소와 원격 저장소 연동하기 git remote -v remote된 원격 저장소 확인하기 git add . git add -A 현재 로컬에 모든 변경사항을 스테이징 하기(커밋을 할 수 있는 상태로 바꾸기) git add 파일경로 파일 경로에 있는 변경사항을 스테이징 하기(커밋을 할 수 있는 상태로 바꾸기 git commit -m "커밋 메세지" 스테이징 된 변경 사항들을 커밋하기 g..
2023.08.17