Search
Duplicate

์นด์นด์˜ค ๋กœ๊ทธ์ธ

์นด์นด์˜ค ๋กœ๊ทธ์ธ

1.
์นด์นด์˜ค ๋กœ๊ทธ์ธ ์†Œ๊ฐœ
a.
์นด์นด์˜ค ๋กœ๊ทธ์ธ ํŠน์ง•
b.
์นด์นด์˜ค ์ œ๊ณต ๊ธฐ๋Šฅ
2.
์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹œ์ž‘ํ•˜๊ธฐ
b.
์‹œ์ž‘ํ•˜๊ธฐ
c.
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ
3.
์นด์นด์˜ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •ํ•˜๊ธฐ
a.
์•ฑ ์„ค์ •
i.
์•ฑ ํ‚ค
1.
REST API ํ‚ค ๋ณต์‚ฌ
ii.
ํ”Œ๋žซํผ
1.
์‚ฌ์ดํŠธ ๋„๋ฉ”์ธ ๋“ฑ๋ก
b.
์ œํ’ˆ ์„ค์ •
i.
์นด์นด์˜ค ๋กœ๊ทธ์ธ
1.
ํ™œ์„ฑํ™” ์„ค์ • ON
2.
Redirect URI ๋“ฑ๋ก
ii.
๋™์˜ ํ•ญ๋ชฉ
1.
๋‹‰๋„ค์ž„
2.
ํ”„๋กœํ•„ ์‚ฌ์ง„
3.
์นด์นด์˜ค ๊ณ„์ •(์ด๋ฉ”์ผ)
c.
๋ณด์•ˆ
i.
Client Secret ํ‚ค ๋ฐœ๊ธ‰
4.
Spring Security x OAuth x ์นด์นด์˜ค ์—ฐ๋™ํ•˜๊ธฐ
a.
ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
b.
์˜์กด์„ฑ ์ถ”๊ฐ€
i.
์ฃผ์š” ์˜์กด์„ฑ
1.
Spring Security
2.
OAuth2 Client
ii.
๊ธฐ๋ณธ ์˜์กด์„ฑ
1.
Spring Web
2.
SpringBoot Devtools
3.
Lombok
4.
Thymeleaf
5.
MySQL Driver
6.
MyBatis Framework
c.
ํ”„๋กœ์ ํŠธ ์„ค์ •
i.
properties profile ํŒŒ์ผ ์ƒ์„ฑ
1.
application-oauth-kakao.properties
ii.
properties profile ํฌํ•จํ•˜๊ธฐ(include)
1.
application.properties
d.
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •
e.
์ปจํŠธ๋กค๋Ÿฌ
i.
HomeController.java
f.
ํ™”๋ฉด
i.
index.html
ii.
login.html

์นด์นด์˜ค ๋กœ๊ทธ์ธ ์†Œ๊ฐœ

์นด์นด์˜ค ๋กœ๊ทธ์ธ ํŠน์ง•

์นด์นด์˜ค ๋กœ๊ทธ์ธ์€ ์นด์นด์˜ค ํ”Œ๋žซํผ์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์นด์นด์˜คํ†ก ์‚ฌ์šฉ์ž๋Š” ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ํ†ตํ•ด ์„œ๋น„์Šค์— ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ๋ถ„์€ ๋” ๋งŽ์€ ๊ณ ๊ฐ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ๋„์ž…ํ•˜๋ฉด ์นด์นด์˜คํ†ก์˜ ๋‹‰๋„ค์ž„๊ณผ ํ”„๋กœํ•„ ์‚ฌ์ง„, ์ด๋ฉ”์ผ, ์„ฑ๋ณ„, ์—ฐ๋ น๋Œ€ ๋“ฑ ์‚ฌ์šฉ์ž์˜ ๋™์˜ ํ•˜์— ์–ป๋Š” ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐœ์ธํ™”๋œ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์ˆ˜๋งŽ์€ ์„œ๋น„์Šค์—์„œ ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์นด์นด์˜ค ๋กœ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ด ๋”์šฑ ํŽธ๋ฆฌํ•œ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค์— ์ง‘์ค‘ํ•˜์„ธ์š”.

์นด์นด์˜ค ์ œ๊ณต ๊ธฐ๋Šฅ

โ€ข
๋กœ๊ทธ์ธ:ย ์นด์นด์˜ค๊ณ„์ •์„ ํ†ตํ•œ ๋น ๋ฅด๊ณ  ๊ฐ„ํŽธํ•œ ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
โ€ข
๋กœ๊ทธ์•„์›ƒ:ย ์‚ฌ์šฉ์ž ํ† ํฐ์„ ๋งŒ๋ฃŒ์‹œ์ผœ ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์—ฐ๊ฒฐ ๋Š๊ธฐ:ย ์นด์นด์˜ค ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ์ž์™€ ์•ฑ์˜ ์—ฐ๊ฒฐ์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
โ€ข
ํ† ํฐ ์ •๋ณด ๋ณด๊ธฐ:ย ์•ก์„ธ์Šค ํ† ํฐ(Access token)์˜ ์ •๋ณด์™€ ํ† ํฐ์˜ ์œ ํšจ๊ธฐ๊ฐ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ:ย ์‚ฌ์šฉ์ž ์นด์นด์˜ค๊ณ„์ •์— ๋“ฑ๋ก๋œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์‚ฌ์šฉ์ž ์ •๋ณด ์ €์žฅํ•˜๊ธฐ:ย ์‚ฌ์šฉ์ž ์นด์นด์˜ค๊ณ„์ •์— ์‚ฌ์šฉ์ž ์ •์˜(Custom)ํ•œ ์„œ๋น„์Šค ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
โ€ข
๋™์˜ ๋‚ด์—ญ ํ™•์ธํ•˜๊ธฐ:ย ์„œ๋น„์Šค์—์„œ ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ด๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์˜ํ•œ ๋™์˜ ํ•ญ๋ชฉ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
โ€ข
๋™์˜ ์ฒ ํšŒํ•˜๊ธฐ:ย ๋ถˆํ•„์š”ํ•œ ๋™์˜ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์‚ฌ์šฉ์ž ๋™์˜๋ฅผ ์ฒ ํšŒํ•ฉ๋‹ˆ๋‹ค.

์นด์นด์˜ค ๋กœ๊ทธ์ธ - Kakao developers

์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹œ์ž‘ํ•˜๊ธฐ

https://developers.kakao.com/product/kakaoLogin

์‹œ์ž‘ํ•˜๊ธฐ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ

์นด์นด์˜ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •ํ•˜๊ธฐ

์•ฑ ์„ค์ •

์•ฑ ํ‚ค

REST API ํ‚ค ๋ณต์‚ฌ

ํ”Œ๋žซํผ

์‚ฌ์ดํŠธ ๋„๋ฉ”์ธ ๋“ฑ๋ก

์ œํ’ˆ ์„ค์ •

์นด์นด์˜ค ๋กœ๊ทธ์ธ

ํ™œ์„ฑํ™” ์„ค์ • ON

Redirect URI ๋“ฑ๋ก

๋™์˜ ํ•ญ๋ชฉ

๋‹‰๋„ค์ž„

ํ”„๋กœํ•„ ์‚ฌ์ง„

์นด์นด์˜ค ๊ณ„์ •(์ด๋ฉ”์ผ)

๋ณด์•ˆ

Client Secret ํ‚ค ๋ฐœ๊ธ‰

Spring Security x OAuth x ์นด์นด์˜ค ์—ฐ๋™ํ•˜๊ธฐ

1.
ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
2.
์˜์กด์„ฑ ์ถ”๊ฐ€
a.
์ฃผ์š” ์˜์กด์„ฑ
i.
Spring Security
ii.
OAuth2 Client
b.
๊ธฐ๋ณธ ์˜์กด์„ฑ
i.
Spring Web
ii.
SpringBoot Devtools
iii.
Lombok
iv.
Thymeleaf
v.
MySQL Driver
vi.
MyBatis Framework
3.
ํ”„๋กœ์ ํŠธ ์„ค์ •
a.
properties profile ํŒŒ์ผ ์ƒ์„ฑ
i.
application-oauth-kakao.properties
b.
properties profile ํฌํ•จํ•˜๊ธฐ(include)
i.
application.properties
4.
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

VS CODE
1.
๋ช…๋ น ํŒ”๋ ˆํŠธ [ctrl + shift + P]
2.
Create a gradle Project ์ž…๋ ฅ
a.
ํ”„๋กœ์ ํŠธ ์„ค์ •
i.
Spring Boot Version
ii.
Language
iii.
Group Id
iv.
Artifact Id
v.
packaging type
vi.
Java version
b.
์˜์กด์„ฑ ์„ค์ •
i.
Spring Web
ii.
Spring boot devtools
iii.
Lombok
iv.
Thymeleaf
v.
MySQL Driver
vi.
Mybatis Framework
vii.
Spring Security
viii.
OAuth2 Client

build.gradle

plugins { id 'java' id 'war' id 'org.springframework.boot' version '2.7.17' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'com.aloha' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { useJUnitPlatform() }
Plain Text
๋ณต์‚ฌ

๋ช…๋ น ํŒ”๋ ˆํŠธ [ctrl + shift + P]

Create a gradle Project ์ž…๋ ฅ

ํ”„๋กœ์ ํŠธ ์„ค์ •

1.
Spring Boot Version
2.
Language
3.
Group Id
4.
Artifact Id
5.
packaging type
6.
Java version

Spring Boot Version

Language

Group Id

Artifact Id

packaging type

Java version

์˜์กด์„ฑ ์„ค์ •

1.
Spring Web
2.
Spring boot devtools
3.
Lombok
4.
Thymeleaf
5.
MySQL Driver
6.
Mybatis Framework
7.
Spring Security
8.
OAuth2 Client

Spring Web

Spring boot devtools

Lombok

Thymeleaf

MySQL Driver

Mybatis Framework

Spring Security

OAuth2 Client

ํ”„๋กœ์ ํŠธ ์„ค์ •

properties profile ํŒŒ์ผ ์ƒ์„ฑ

application-oauth-kakao.properties

#Kakao OAuth Settings spring.security.oauth2.client.registration.kakao.client-id=[REST API ํ‚ค] spring.security.oauth2.client.registration.kakao.client-secret=[Client Secret ์ฝ”๋“œ] spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:8080/login/oauth2/code/kakao spring.security.oauth2.client.registration.kakao.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.kakao.scope=profile_nickname, account_email, profile_image spring.security.oauth2.client.registration.kakao.client-name=Kakao spring.security.oauth2.client.registration.kakao.client-authentication-method=POST spring.security.oauth2.client.provider.kakao.authorization-uri=https://kauth.kakao.com/oauth/authorize spring.security.oauth2.client.provider.kakao.token-uri=https://kauth.kakao.com/oauth/token spring.security.oauth2.client.provider.kakao.user-info-uri=https://kapi.kakao.com/v2/user/me spring.security.oauth2.client.provider.kakao.user-name-attribute=id
Plain Text
๋ณต์‚ฌ

application-oauth-kakao.properties (์„ค๋ช… ํฌํ•จ)

#Kakao OAuth Settings # client-id : REST API KEY spring.security.oauth2.client.registration.kakao.client-id=[REST API ํ‚ค] # client-secret : ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ > ๋ณด์•ˆ > Client secret spring.security.oauth2.client.registration.kakao.client-secret=[Client Secret ์ฝ”๋“œ] # redirect-uri : ์‚ฌ์šฉ์ž๊ฐ€ ์นด์นด์˜ค๋กœ ๋กœ๊ทธ์ธ ํ›„ ๋Œ์•„์˜ฌ ์„œ๋ฒ„์˜ URL spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:8080/login/oauth2/code/kakao # authorization-grant-type : ์•ก์„ธ์Šค ํ† ํฐ ์š”์ฒญ ์‹œ, ์œ ํ˜•์„ ์ง€์ •ํ•˜๋Š” ํ—ค๋” ์†์„ฑ spring.security.oauth2.client.registration.kakao.authorization-grant-type=authorization_code # scope : ์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๋Š” ์†์„ฑ spring.security.oauth2.client.registration.kakao.scope=profile_nickname, account_email, profile_image # client-name : ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•œ ์ด๋ฆ„ spring.security.oauth2.client.registration.kakao.client-name=Kakao # client-authentication-method : ์ธ์ฆ ์„œ๋ฒ„๋กœ ์š”์ฒญ ์‹œ, ์ง€์ •ํ•  ์š”์ฒญ ๋ฉ”์†Œ๋“œ spring.security.oauth2.client.registration.kakao.client-authentication-method=POST # authorization-uri : ์ธ๊ฐ€ ์ฝ”๋“œ ์š”์ฒญ URI (์ธ์ฆ ์„œ๋ฒ„) spring.security.oauth2.client.provider.kakao.authorization-uri=https://kauth.kakao.com/oauth/authorize # token-uri : ์•ก์„ธ์Šค ํ† ํฐ ์š”์ฒญ URI (์ธ์ฆ ์„œ๋ฒ„) spring.security.oauth2.client.provider.kakao.token-uri=https://kauth.kakao.com/oauth/token # user-info-uri : ์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ URI (๋ฆฌ์†Œ์Šค ์„œ๋ฒ„) spring.security.oauth2.client.provider.kakao.user-info-uri=https://kapi.kakao.com/v2/user/me # user-name-attribute : ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ณ ์œ  ์‹๋ณ„๊ฐ€ ํ‚ค ์†์„ฑ spring.security.oauth2.client.provider.kakao.user-name-attribute=id
Plain Text
๋ณต์‚ฌ

REST API ๊ฐ€์ ธ์˜ค๊ธฐ

2.
๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
3.
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ ํƒ
4.
[์•ฑ ์„ค์ •] > [์•ฑ ํ‚ค]
a.
๋„ค์ดํŠธ๋ธŒ ์•ฑ ํ‚ค
b.
REST API ํ‚ค
c.
JavaScript ํ‚ค
d.
Admin ํ‚ค
์—ฌ๊ธฐ์„œ REST API ํ‚ค๋ฅผ ๋ณต์‚ฌํ•ด์„œ spring.security.oauth2.client.registration.kakao.client-id ์†์„ฑ๊ฐ’์œผ๋กœ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
# client-id : REST API KEY spring.security.oauth2.client.registration.kakao.client-id=[REST API ํ‚ค]
Plain Text
๋ณต์‚ฌ

Client Secret ๊ฐ€์ ธ์˜ค๊ธฐ

2.
๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
3.
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ ํƒ
4.
[์ œํ’ˆ ์„ค์ •] > [์นด์นด์˜ค ๋กœ๊ทธ์ธ] > [๋ณด์•ˆ]
a.
์ฝ”๋“œ

properties profile ํฌํ•จํ•˜๊ธฐ(include)

1.
ํ”„๋กœํ•„ ํŒŒ์ผ ์ž‘์„ฑ
2.
ํ”„๋กœํ•„ ํŒŒ์ผ ํฌํ•จ

ํ”„๋กœํ•„ ํŒŒ์ผ ์ž‘์„ฑ

ํ”„๋กœํ•„ ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
application-[ํ”„๋กœํ•„์ด๋ฆ„].properties
Plain Text
๋ณต์‚ฌ
์—ฌ๊ธฐ์„œ๋Š” ์ด๋ ‡๊ฒŒ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ด€๋ จ ์†์„ฑ์„ ๋‹ด๊ณ  ์žˆ๋Š” ํ”„๋กœํ•„ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
application-oauth-kakao.properties
Plain Text
๋ณต์‚ฌ

ํ”„๋กœํ•„ ํŒŒ์ผ ํฌํ•จ

ํ”„๋กœํ•„ ํŒŒ์ผ์€ application.properties ํŒŒ์ผ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์†์„ฑ์„ ์ž‘์„ฑํ•˜๋ฉด ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋งŽ์€ ์†์„ฑ ์ •๋ณด๋“ค์„ ํŒŒ์ผ ๋‹จ์œ„๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
application.properties
spring.profiles.include=[ํ”„๋กœํ•„์ด๋ฆ„]
Plain Text
๋ณต์‚ฌ
์—ฌ๊ธฐ์„œ๋Š” oauth-kakao ์ด๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ”„๋กœํ•„ ํŒŒ์ผ์„ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.
โ€ข
application.properties
spring.profiles.include=oauth-kakao
Plain Text
๋ณต์‚ฌ

application.properties

spring.application.name=kakao # profile ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ ํฌํ•จํ•˜๊ธฐ # application-[ํ”„๋กœํ•„์ด๋ฆ„].properties # application-oauth-kakao.properties spring.profiles.include=oauth-kakao
Plain Text
๋ณต์‚ฌ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

1.
SecurityConfig.java ํŒŒ์ผ ์ƒ์„ฑ
2.
์ฝ”๋“œ ์ž‘์„ฑ
package com.aloha.kakao.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ • ๋ฉ”์†Œ๋“œ @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // OAuth ๋กœ๊ทธ์ธ ์„ค์ • http.oauth2Login(login -> login .loginPage("/login") ); return http.build(); } }
Java
๋ณต์‚ฌ

์ปจํŠธ๋กค๋Ÿฌ

1.
HomeController.java

HomeController.java

package com.aloha.kakao.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { @GetMapping({"/", ""}) public String home() { return "index"; } @GetMapping("/login") public String login() { return "login"; } }
Java
๋ณต์‚ฌ

ํ™”๋ฉด

2.
๋ฉ”์ธ ํ™”๋ฉด
a.
index.html
3.
๋กœ๊ทธ์ธ ํ™”๋ฉด
a.
login.html

์นด์นด์˜ค ๋””์ž์ธ ๊ฐ€์ด๋“œ

์นด์นด์˜ค ๋””์ž์ธ ์‚ฌ์ดํŠธ์— ๊ฐ€๋ฉด, ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ์ด๋ฏธ์ง€๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์„œ ์ ์ ˆํ•œ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๋ฉ”์ธ ํ™”๋ฉด

index.html

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> <head> <meta charset="UTF-8"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด</title> <!-- ํŒŒ๋น„์ฝ˜ --> <link rel="icon" href="/img/logo.png" type="image/x-icon"> <!-- ์ธ๋„ค์ผ ์ด๋ฏธ์ง€ ์„ค์ • --> <meta property="og:image" content="https://i.imgur.com/tXd2rVi.png"> <!-- ์›น ํŽ˜์ด์ง€ ์„ค๋ช… (์„ ํƒ ์‚ฌํ•ญ) --> <meta property="og:description" content="ALOHA CLASS๐ŸŒด - ์†Œ์…œ ๋กœ๊ทธ์ธ"> <!-- ์›น ํŽ˜์ด์ง€ URL --> <meta property="og:url" content=""> <!-- ์›น ํŽ˜์ด์ง€ ์ œ๋ชฉ --> <meta name="title" content="์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด"> <meta property="og:title" content="์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด"> <!-- ์›น ํŽ˜์ด์ง€ ํƒ€์ž… (์›น์‚ฌ์ดํŠธ, ๊ธฐ์‚ฌ, ์ œํ’ˆ ๋“ฑ) --> <meta property="og:type" content="website"> <!-- ๊ฒ€์ƒ‰์–ด --> <meta name="keywords" content="์†Œ์…œ ๋กœ๊ทธ์ธ์ž๋ฐ” ์›น๊ฐœ๋ฐœ, ALOHA CLASS, ์•Œ๋กœํ•˜ ํด๋ž˜์Šค"> <meta name="robots" content="index, follow"> <!-- ์‚ฌ์ดํŠธ ๋งต --> <link rel="sitemap" href="/static/sitemap.xml"> <!-- bootstrap lib --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous"> <!-- Noto Sans font --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&amp;display=swap"> <!-- material design icon --> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"> </head> <body> <div class="container col-6 col-lg-4"> <div class="px-4 py-5 mt-5 text-center"> <h1 class="display-5 fw-bold text-body-emphasis">๋กœ๊ทธ์ธ</h1> </div> <!-- ๋น„ ๋กœ๊ทธ์ธ ์‹œ --> <th:block sec:authorize="isAnonymous()"> <div class="d-grid gap-2"> <a href="/login" class="btn btn-lg btn-primary">๋กœ๊ทธ์ธ</a> </div> </th:block> <!-- ๋กœ๊ทธ์ธ ์‹œ --> <th:block sec:authorize="isAuthenticated()"> <div class="card" th:if="${session.user != null}"> <div class="inner p-4"> <div class="d-flex flex-column align-items-center"> <div class="item my-2"> <!-- ํ”„๋กœํ•„ ์‚ฌ์ง„ --> <th:block th:if="${session.user.profile == null}"> <img src="/img/profile.png" class="rounded-circle shadow-4 border" width="110" alt="ํ”„๋กœํ•„" > </th:block> <th:block th:if="${session.user.profile != null}"> <img th:src="${session.user.profile}" class="rounded-circle shadow-4 border" width="110" alt="ํ”„๋กœํ•„"> </th:block> </div> <div class="item my-2"> <!-- ๋‹‰๋„ค์ž„ --> <h3 th:text="${session.user.name}"></h3> </div> <div class="item my-2"> <!-- ์ด๋ฉ”์ผ --> <h3 th:text="${session.user.email}"></h3> </div> </div> </div> </div> <form action="/logout" method="post"> <!-- CSRF TOKEN --> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"> <div class="d-grid gap-2"> <button type="submit" class="btn btn-lg btn-primary">๋กœ๊ทธ์•„์›ƒ</button> </div> </form> </th:block> </div> </body> </html>
HTML
๋ณต์‚ฌ

๋กœ๊ทธ์ธ ํ™”๋ฉด

login.html

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> <head> <meta charset="UTF-8"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด</title> <!-- ํŒŒ๋น„์ฝ˜ --> <link rel="icon" href="/img/logo.png" type="image/x-icon"> <!-- ์ธ๋„ค์ผ ์ด๋ฏธ์ง€ ์„ค์ • --> <meta property="og:image" content="https://i.imgur.com/tXd2rVi.png"> <!-- ์›น ํŽ˜์ด์ง€ ์„ค๋ช… (์„ ํƒ ์‚ฌํ•ญ) --> <meta property="og:description" content="ALOHA CLASS๐ŸŒด - ์†Œ์…œ ๋กœ๊ทธ์ธ"> <!-- ์›น ํŽ˜์ด์ง€ URL --> <meta property="og:url" content=""> <!-- ์›น ํŽ˜์ด์ง€ ์ œ๋ชฉ --> <meta name="title" content="์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด"> <meta property="og:title" content="์นด์นด์˜ค ๋กœ๊ทธ์ธ๐Ÿ” - ALOHA CLASS๐ŸŒด"> <!-- ์›น ํŽ˜์ด์ง€ ํƒ€์ž… (์›น์‚ฌ์ดํŠธ, ๊ธฐ์‚ฌ, ์ œํ’ˆ ๋“ฑ) --> <meta property="og:type" content="website"> <!-- ๊ฒ€์ƒ‰์–ด --> <meta name="keywords" content="์†Œ์…œ ๋กœ๊ทธ์ธ์ž๋ฐ” ์›น๊ฐœ๋ฐœ, ALOHA CLASS, ์•Œ๋กœํ•˜ ํด๋ž˜์Šค"> <meta name="robots" content="index, follow"> <!-- ์‚ฌ์ดํŠธ ๋งต --> <link rel="sitemap" href="/static/sitemap.xml"> <!-- bootstrap lib --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- Noto Sans font --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&amp;display=swap"> <!-- material design icon --> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"> </head> <body> <div class="container col-12 col-md-6 col-lg-4"> <div class="px-4 py-5 mt-5 text-center"> <h1 class="display-5 fw-bold text-body-emphasis">๋กœ๊ทธ์ธ</h1> </div> <!-- ๋กœ๊ทธ์ธ ์˜์—ญ --> <main class="form-signin login-box w-100 m-auto"> <form action="/login" method="post"> <!-- CSRF TOKEN --> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"> <div class="form-floating"> <input type="text" class="form-control" id="floatingInput" name="username" value="" placeholder="์•„์ด๋””" autofocus th:value="${userId}"> <label for="floatingInput">์•„์ด๋””</label> </div> <div class="form-floating"> <input type="password" class="form-control" id="floatingPassword" name="password" placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ"> <label for="floatingPassword">๋น„๋ฐ€๋ฒˆํ˜ธ</label> </div> <div class="form-check text-start my-3 d-flex justify-content-around"> <div class="item"> <input class="form-check-input" type="checkbox" name="remember-id" id="flexCheckDefault1" th:checked="${rememberId}"> <label class="form-check-label" for="flexCheckDefault1">์•„์ด๋”” ์ €์žฅ</label> </div> <div class="item"> <input class="form-check-input" type="checkbox" name="remember-me" id="flexCheckDefault2"> <label class="form-check-label" for="flexCheckDefault2">์ž๋™ ๋กœ๊ทธ์ธ</label> </div> </div> <!-- ๋กœ๊ทธ์ธ ์—๋Ÿฌ --> <th:block th:if="${param.error}"> <p class="text-center text-danger">์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.</p> </th:block> <div class="d-grid gap-2"> <button class="btn btn-lg btn-primary w-100 py-2" type="submit">๋กœ๊ทธ์ธ</button> <a href="/join" class="btn btn-lg btn-success w-100 py-2">ํšŒ์›๊ฐ€์ž…</a> <hr> <a href="/oauth2/authorization/kakao"> <img src="/img/kakao_login_large.png" width="100%" alt="์นด์นด์˜ค ๋กœ๊ทธ์ธ"> </a> </div> </form> </main> </div> <!-- bootstrap --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
HTML
๋ณต์‚ฌ