{"id":80,"date":"2020-03-11T15:47:12","date_gmt":"2020-03-11T06:47:12","guid":{"rendered":"http:\/\/www.skyer9.pe.kr\/wordpress\/?p=80"},"modified":"2020-10-31T13:38:07","modified_gmt":"2020-10-31T04:38:07","slug":"from-hello-to-querydsl-simple-board-2-12","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=80","title":{"rendered":"[From Hello To QueryDSL] Simple Board (2\/12)"},"content":{"rendered":"<h1>Simple Board<\/h1>\n<p>\uac8c\uc2dc\ubb3c\uc744 \uc785\ub825\/\uc218\uc815\/\uc0ad\uc81c\/\ub9ac\uc2a4\ud2b8\ud45c\uc2dc \ud558\ub294 \uac8c\uc2dc\ud310\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<p>\uac80\uc0c9\uae30\ub2a5\uc774\ub098 \ud398\uc774\uc9d5 \uae30\ub2a5\uc740 \ub2e4\uc74c \uae00\uc5d0\uc11c \ucd94\uac00\ud558\uae30\uc5d0 \uc5ec\uae30\uc11c\ub294 \uc81c\uc678\ub429\ub2c8\ub2e4.<\/p>\n<h2>\uac1c\ubc1c\ud658\uacbd<\/h2>\n<ul>\n<li>Spring Boot 2.1.x<\/li>\n<li>Gradle 4.10.2<\/li>\n<\/ul>\n<p>\ud504\ub85c\uc81d\ud2b8\ub294 \uc774\uc804 \uae00\uc5d0\uc11c \uc791\uc131\ub41c \ud504\ub85c\uc81d\ud2b8\uc5d0 \ud30c\uc77c\uc744 \ucd94\uac00 \ub610\ub294 \uc218\uc815\ud558\ub294 \ubc29\uc2dd\uc73c\ub85c \uc9c4\ud589\ub429\ub2c8\ub2e4. \uc774\uc804 \uae00\uc744 \ub530\ub77c \ud558\uc9c0 \uc54a\uc740 \uacbd\uc6b0, \uba3c\uc800 \uc774\uc804 \uae00\ub300\ub85c \ud504\ub85c\uc81d\ud2b8\ub97c \uad6c\uc131\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.<\/p>\n<p>Lombok \uc774 \ucc98\uc74c\uc774\uc2e0 \ubd84\uc740 <a href=\"http:\/\/www.skyer9.pe.kr\/wordpress\/?p=100\">\uc5ec\uae30<\/a> \ub97c \uba3c\uc800 \ud655\uc778\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.<\/p>\n<h2>\ud30c\uc77c \uc218\uc815 \uc21c\uc11c<\/h2>\n<p>\uba3c\uc800 <code>build.gradle<\/code> \uc744 \uc218\uc815\ud569\ub2c8\ub2e4. <code>build.gradle<\/code> \uc5d0 \uc758\uc874\uc131\uc744 \ucd94\uac00\ud574\uc11c \uae30\ub2a5\uc744 \ud655\uc7a5\ud569\ub2c8\ub2e4.<\/p>\n<p>\ub2e4\uc74c\uc740 <code>config<\/code>, <code>domain<\/code>, <code>service<\/code>, <code>web<\/code> \uc744 \ucd94\uac00\ud569\ub2c8\ub2e4.<\/p>\n<p><code>config<\/code> \ub808\uc774\uc5b4\uc5d0\ub294 \uac01\uc885 \uc124\uc815\ud30c\uc77c\ub4e4\uc774 \ubc30\uce58\ub429\ub2c8\ub2e4. Spring Boot \uc5d0\uc11c\ub294 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\ub3c4 \uc124\uc815\uc744 \ucd94\uac00\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p><code>domain<\/code> \ub808\uc774\uc5b4\uc5d0\ub294 \ub3c4\uba54\uc778 \uc601\uc5ed\uc758 <code>Entity<\/code>, <code>Repository<\/code> \ud30c\uc77c\ub4e4\uc774 \ucd94\uac00\ub429\ub2c8\ub2e4. <code>Entity<\/code> \ub294 \ub370\uc774\ud0c0\ubca0\uc774\uc2a4 \ud14c\uc774\ube14\uacfc 1:1 \ub85c \ub300\uc751\ud569\ub2c8\ub2e4. <code>Repository<\/code> \ub85c \ud14c\uc774\ube14\uc758 CRUD \ub97c \uc218\ud589\ud569\ub2c8\ub2e4.<\/p>\n<p><code>service<\/code> \ub808\uc774\uc5b4\ub294 <code>domain<\/code>, <code>web<\/code> \ub450 \ub808\uc774\uc5b4\uac00 \uc11e\uc774\uc9c0 \uc54a\ub3c4\ub85d \uc911\uac04\ub2e8\uacc4 \uc5ed\ud65c\uc744 \ud569\ub2c8\ub2e4.<\/p>\n<p><code>web<\/code> \ub808\uc774\uc5b4\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0 \ub178\ucd9c\ub418\ub294 html \uacfc \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \uc804\ub2ec\ubc1b\ub294 \ud30c\ub77c\ubbf8\ud130\ub97c \ucc98\ub9ac\ud558\ub294 \uc5ed\ud65c\uc744 \ud569\ub2c8\ub2e4.<\/p>\n<h2>build.gradle \uc218\uc815<\/h2>\n<p><code>build.gradle<\/code> \uc5d0 \ub2e4\uc74c \uc758\uc874\uc131\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4.<\/p>\n<p><code>h2<\/code> \ub294 \ub370\uc774\ud0c0\ubca0\uc774\uc2a4\ub85c \uae30\ubcf8\uc801\uc73c\ub85c \uba54\ubaa8\ub9ac\uc5d0 \ub370\uc774\ud0c0\ub97c \uc800\uc7a5\ud558\ubbc0\ub85c \ud1b0\ucea3\uc744 \uc7ac\uc2e4\ud589\ud560 \ub54c\ub9c8\ub2e4 \ub370\uc774\ud0c0\uac00 \uc0ac\ub77c\uc9d1\ub2c8\ub2e4. \uac1c\ubc1c\uc6a9\uc73c\ub85c\ub294 \uc4f0\uae30 \ud3b8\ud574\uc11c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-gradle\">dependencies {\n    \/\/ ......\n    compile(&#039;org.springframework.boot:spring-boot-starter-data-jdbc&#039;)\n    compile(&#039;org.springframework.boot:spring-boot-starter-data-jpa&#039;)\n    compile(&#039;com.h2database:h2&#039;)\n    \/\/ ......\n}<\/code><\/pre>\n<h2>config \ub808\uc774\uc5b4<\/h2>\n<p><code>Spring Boot<\/code> \ub294 \uc124\uc815\ud30c\uc77c\uc5d0 \uc124\uc815\uc744 \ucd94\uac00\ud558\ub294 \ubc29\uc2dd \ubfd0\ub9cc \uc544\ub2c8\ub77c, \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc124\uc815\uc744 \ucd94\uac00\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. <code>@Configuration<\/code> \uc744 \ucd94\uac00\ud568\uc73c\ub85c \ud574\uc11c \uc774 \ud074\ub798\uc2a4\ub294 \uc124\uc815\uc744 \uc704\ud55c \ud074\ub798\uc2a4\uc784\uc744 \uc54c\ub824\uc90d\ub2c8\ub2e4. <code>@EnableJpaAuditing<\/code> \uc740 JPA \ub97c \ud65c\uc131\ud654 \ud568\uc744 \ud45c\uc2dc\ud569\ub2c8\ub2e4.<\/p>\n<p>JPA \ub294 Raw \ucffc\ub9ac \uae30\ubc18\uc758 JDBC \ub97c \ud6e8\uc52c \uba4b\uc788\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uac8c \ubc14\uafd4\uc90d\ub2c8\ub2e4. \uc5b4\ub5bb\uac8c \ubc14\ub00c\ub294\uc9c0\ub294 \uc544\ub798\uc5d0\uc11c \uc124\uba85\ud569\ub2c8\ub2e4.<\/p>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/JpaConfig.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.jpa.repository.config.EnableJpaAuditing;\n\n@Configuration\n@EnableJpaAuditing\npublic class JpaConfig {\n}<\/code><\/pre>\n<h2>domain \ub808\uc774\uc5b4<\/h2>\n<p>\ub370\uc774\ud0c0\ub9c8\ub2e4 createdDate\/modifiedDate \ub97c \ub9e4\ubc88 \uc785\ub825\ud558\uace0 \uc5c5\ub370\uc774\ud2b8 \ud574\uc57c \ud558\ub358\uac78 \ud55c\ubc88\uc5d0 \ud574\uacb0\ud574\uc8fc\ub294 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. \uc77c\ub2e8, \uc65c \uc774\ub807\uac8c \ub418\ub294\uc9c0\ub294 \ub098\uc911\uc5d0 \uc54c\uc544\ubcf4\uace0 \uc815\ub9d0 \uc790\ub3d9\uc73c\ub85c \uc5c5\ub370\uc774\ud2b8 \ub418\ub294\uc9c0 \ubcf4\ub3c4\ub85d \ud569\ub2c8\ub2e4.<\/p>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/BaseTimeEntity.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.domain;\n\nimport lombok.Getter;\nimport org.springframework.data.annotation.CreatedDate;\nimport org.springframework.data.annotation.LastModifiedDate;\nimport org.springframework.data.jpa.domain.support.AuditingEntityListener;\n\nimport javax.persistence.EntityListeners;\nimport javax.persistence.MappedSuperclass;\nimport java.time.LocalDateTime;\n\n@Getter\n@MappedSuperclass\n@EntityListeners(AuditingEntityListener.class)\npublic class BaseTimeEntity {\n\n    @CreatedDate\n    private LocalDateTime createdDate;\n\n    @LastModifiedDate\n    private LocalDateTime modifiedDate;\n}<\/code><\/pre>\n<p><code>@Entity<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \uc90c\uc73c\ub85c \ud574\uc11c \uc774 \ud074\ub798\uc2a4\ub294 \ub370\uc774\ud0c0\ubca0\uc774\uc2a4 \uc0c1\uc758 \ud14c\uc774\ube14\uacfc 1:1 \ub300\uc751\ud568\uc744 \ud45c\uc2dc\ud569\ub2c8\ub2e4. \ub0b4\ubd80\ubcc0\uc218 \ud558\ub098 \ud558\ub098\uac00 DB \ud14c\uc774\ube14\uc758 \ud544\ub4dc\uc5d0 \ud574\ub2f9\ud569\ub2c8\ub2e4. <code>@Id<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc740 PK \ub97c \uc758\ubbf8\ud569\ub2c8\ub2e4.<\/p>\n<p>\ubd84\uba85 \ub0b4\ubd80\ubcc0\uc218\uc5d0 createdDate\/modifiedDate \uac00 \uc5c6\uc74c\uc5d0\ub3c4 \uc790\ub3d9\uc73c\ub85c \ud14c\uc774\ube14\uc5d0\ub294 createdDate\/modifiedDate \uac00 \ucd94\uac00\ub420\uac83\uc785\ub2c8\ub2e4.<\/p>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/posts\/Posts.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.domain.posts;\n\nimport kr.co.episode.example.domain.BaseTimeEntity;\nimport lombok.Builder;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.*;\n\n@Getter\n@NoArgsConstructor\n@Entity\npublic class Posts extends BaseTimeEntity {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private long id;\n\n    @Column(length = 500, nullable = false)\n    private String title;\n\n    @Column(columnDefinition = &quot;TEXT&quot;, nullable = false)\n    private String content;\n\n    private String author;\n\n    @Builder\n    public Posts(String title, String content, String author) {\n        this.title = title;\n        this.content = content;\n        this.author = author;\n    }\n\n    public void update(String title, String content) {\n        this.title = title;\n        this.content = content;\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/posts\/PostsRepository.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.domain.posts;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\n\nimport java.util.List;\n\npublic interface PostsRepository extends JpaRepository&lt;Posts, Long&gt; {\n\n    @Query(value = &quot;SELECT p FROM Posts p ORDER BY p.id DESC&quot;)\n    List&lt;Posts&gt; findAllDesc();\n}<\/code><\/pre>\n<p>\uc9dc\uc794!! CRUD \uac00 \ub05d\ub0ac\uc2b5\ub2c8\ub2e4. JPA \uac00 \uc774\ub7f0 \uac81\ub2c8\ub2e4.<\/p>\n<p>\uc0ac\uc2e4 \ub9c8\ubc95\uc740 \uc5c6\ub294\uac8c&#8230; insert\/update\/delete \ubaa8\ub450 \uac1c\ubc1c\uc790\uac00 \uae30\uacc4\uc801\uc73c\ub85c \ucf54\ub529\ud558\uace0 \uc788\ub358\uac78 \uc790\ub3d9\ud654 \ud55c\uac83\uc5d0 \ubd88\uacfc\ud569\ub2c8\ub2e4.<\/p>\n<p>select \ub294 \ud55c\uac74 \uc870\ud68c\ub294 \uc5ed\uc2dc \uae30\uacc4\uc801\uc73c\ub85c \ucf54\ub529\ud558\ub294 \ubd80\ubd84\uc774\ub77c \uc5ed\uc2dc \uc790\ub3d9\ud654\uac00 \ub429\ub2c8\ub2e4.<\/p>\n<p>list \uac00\uc838\uc624\ub294 \uae30\ub2a5\uc774 \ubcf5\uc7a1\ud558\uace0 JPA \uc5d0\uc11c\ub3c4 \ucee4\ubc84 \ubabb\ud558\ub294 \ubd80\ubd84\uc778\ub370&#8230; \uc77c\ub2e8 \uc704\uc5d0\uc11c\ub294 \uac00\uc7a5 \ub2e8\uc21c\ud558\uac8c \uac80\uc0c9\uc870\uac74\/\ud398\uc774\uc9d5\ub3c4 \uc5c6\uc774 \uc804\uccb4\ub0b4\uc5ed \uac00\uc838\uc624\ub3c4\ub85d \ucf54\ub529\ud588\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc704\uc5d0 \ud45c\uc2dc\ub41c <code>@Query<\/code> \ub294 \uc6b0\ub9ac\uac00 \uc544\ub294 \uc77c\ubc18\uc801\uc778 \ucffc\ub9ac\uac00 \uc544\ub2c8\uace0, JPQL \uc774\ub77c\uace0 \ud558\ub294 \uc0c8\ub85c\uc6b4 \ucffc\ub9ac\uc785\ub2c8\ub2e4. \uadf8\ub9ac\uace0 JPQL \uc740 \ub300\uc18c\ubb38\uc790\ub97c \uad6c\ubd84\ud569\ub2c8\ub2e4.<\/p>\n<h2>service \ub808\uc774\uc5b4<\/h2>\n<p>service \ub808\uc774\uc5b4\ub294 domain \ub808\uc774\uc5b4\uc640 web \ub808\uc774\uc5b4\uac00 \uc11e\uc774\ub294 \ub808\uc774\uc5b4\ub77c web \ub808\uc774\uc5b4\uc758 \uc77c\ubd80 \ud074\ub798\uc2a4\ub97c \uba3c\uc800 \uc0dd\uc131\ud574\uc8fc\uc5b4\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<h3>DTO \ud074\ub798\uc2a4 \uc0dd\uc131<\/h3>\n<p><code>Entity<\/code> \ub294 DB \ud14c\uc774\ube14\uacfc 1:1 \ub300\uc751\ud558\ub294 \uac1d\uccb4\uc774\uace0, \uadf8\uc640 \ub2ec\ub9ac Web \uc5d0 \ub300\uc751\ud558\ub294 \uac1d\uccb4\uac00 \ud544\uc694\ud55c\ub370 DTO(Data Transfer Object) \uac00 \uadf8 \uae30\ub2a5\uc744 \ud569\ub2c8\ub2e4.<\/p>\n<p>\uc774\ubc88 \ud504\ub85c\uc81d\ud2b8\ub294 \ub2e8\uc21c\ud55c \ud504\ub85c\uc81d\ud2b8\uc774\uae30\uc5d0 Entity \uac1d\uccb4\uc640 DTO \uac1d\uccb4\uac00 \uac70\uc758 \uc720\uc0ac\ud558\uc9c0\ub9cc, \uc2e4\ubb34\uc5d0\uc11c\ub294 \ub9e4\uc6b0 \ub2e4\ub978 \uacbd\uc6b0\uac00 \ub9ce\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc544\ub798\uc5d0 \uc774\ubc88 \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc4f0\uc77c 4\uac1c\uc758 DTO \uac1d\uccb4\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/dto\/PostsListResponseDto.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web.dto;\n\nimport kr.co.episode.example.domain.posts.Posts;\nimport lombok.Getter;\n\nimport java.io.Serializable;\nimport java.time.LocalDateTime;\n\n@Getter\npublic class PostsListResponseDto implements Serializable {\n\n    private Long id;\n    private String title;\n    private String author;\n    private LocalDateTime modifiedDate;\n\n    public String getLink() {\n        return &quot;\/posts\/update\/&quot; + id;\n    }\n    public PostsListResponseDto(Posts entity) {\n        this.id = entity.getId();\n        this.title = entity.getTitle();\n        this.author = entity.getAuthor();\n        this.modifiedDate = entity.getModifiedDate();\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/dto\/PostsResponseDto.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web.dto;\n\nimport kr.co.episode.example.domain.posts.Posts;\nimport lombok.Getter;\n\nimport java.io.Serializable;\n\n@Getter\npublic class PostsResponseDto implements Serializable {\n\n    private Long id;\n    private String title;\n    private String content;\n    private String author;\n\n    public PostsResponseDto(Posts entity) {\n        this.id = entity.getId();\n        this.title = entity.getTitle();\n        this.content = entity.getContent();\n        this.author = entity.getAuthor();\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/dto\/PostsSaveRequestDto.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web.dto;\n\nimport kr.co.episode.example.domain.posts.Posts;\nimport lombok.Builder;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\n@Getter\n@NoArgsConstructor\npublic class PostsSaveRequestDto {\n\n    private String title;\n    private String content;\n    private String author;\n\n    @Builder\n    public PostsSaveRequestDto(String title, String content, String author) {\n        this.title = title;\n        this.content = content;\n        this.author = author;\n    }\n\n    public Posts toEntity() {\n        return Posts.builder()\n                .title(title)\n                .content(content)\n                .author(author)\n                .build();\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/dto\/PostsUpdateRequestDto.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web.dto;\n\nimport lombok.Builder;\nimport lombok.Getter;\n\n@Getter\n@NoArgsConstructor\npublic class PostsUpdateRequestDto {\n\n    private String title;\n    private String content;\n\n    @Builder\n    public PostsUpdateRequestDto(String title, String content) {\n        this.title = title;\n        this.content = content;\n    }\n}<\/code><\/pre>\n<h3>service \ud074\ub798\uc2a4 \uc0dd\uc131<\/h3>\n<p>src\/main\/java\/kr\/co\/episode\/example\/service\/posts\/PostsService.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.service.posts;\n\nimport kr.co.episode.example.domain.posts.Posts;\nimport kr.co.episode.example.domain.posts.PostsRepository;\nimport kr.co.episode.example.web.dto.PostsListResponseDto;\nimport kr.co.episode.example.web.dto.PostsResponseDto;\nimport kr.co.episode.example.web.dto.PostsSaveRequestDto;\nimport kr.co.episode.example.web.dto.PostsUpdateRequestDto;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n@RequiredArgsConstructor\n@Service\npublic class PostsService {\n\n    private final PostsRepository postsRepository;\n\n    @Transactional\n    public Long save(PostsSaveRequestDto postsSaveRequestDto) {\n        return postsRepository.save(postsSaveRequestDto.toEntity()).getId();\n    }\n\n    @Transactional\n    public Long update(Long id, PostsUpdateRequestDto postsUpdateRequestDto) {\n        Posts posts = getOne(id);\n\n        posts.update(postsUpdateRequestDto.getTitle(), postsUpdateRequestDto.getContent());\n\n        return id;\n    }\n\n    public PostsResponseDto findById(Long id) {\n        Posts posts = getOne(id);\n\n        return new PostsResponseDto(posts);\n    }\n\n    @Transactional(readOnly = true)\n    public List&lt;PostsListResponseDto&gt; findAllDesc() {\n        return postsRepository.findAllDesc().stream()\n                .map(PostsListResponseDto::new)\n                .collect(Collectors.toList());\n    }\n\n    @Transactional\n    public void delete(Long id) {\n        Posts posts = getOne(id);\n        postsRepository.delete(posts);\n    }\n\n    private Posts getOne(Long id) throws IllegalArgumentException {\n        return postsRepository.findById(id).orElseThrow(() -&gt;\n                new IllegalArgumentException(&quot;\ud574\ub2f9 \uac8c\uc2dc\ubb3c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.[id=&quot; + id + &quot;]&quot;));\n    }\n}<\/code><\/pre>\n<p><code>@Service<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uc5b4\uc11c \uc774 \ud074\ub798\uc2a4\uac00 \uc11c\ube44\uc2a4 \ud074\ub798\uc2a4\uc784\uc744 \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0 \uc778\uc2dd\uc2dc\ucf1c \uc90d\ub2c8\ub2e4.<\/p>\n<p><code>PostsRepository<\/code> \ub97c \uc774\uc6a9\ud558\uace0 \uc788\ub294\ub370&#8230; \uc774 \ub188\uc740 \uc5b8\uc81c \ub204\uac00 \uc0dd\uc131\ud560\uae4c? Spring Boot \ub294 \ud1b0\ucea3\uc2e4\ud589\uc2dc <code>@Service<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc774 \ubd99\uc5b4\uc788\ub294 \ud074\ub798\uc2a4\ub3c4 \uc790\ub3d9\uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<p>\uadf8\ub7f0\ub370 <code>@RequiredArgsConstructor<\/code> \uc5b4\ub178\ud14c\uc774\uc158\uc774 \ubd99\uc5b4\uc788\uace0, \uadf8\ub7ec\uba74 <code>final<\/code> \uc774 \ubd99\uc5b4\uc788\ub294 \ub0b4\ubd80\ubcc0\uc218\ub97c \ucd08\uae30\ud654 \ud558\ub294 \uc0dd\uc131\uc790\uac00 \uc790\ub3d9\uc0dd\uc131\ub418\uace0, Spring Boot \ub294 \uadf8\uac83\uc744 \ucd08\uae30\ud654 \ud560 \uc218 \uc788\ub294 \ud074\ub798\uc2a4\ub3c4 \uc790\ub3d9\uc0dd\uc131\ud574 \uc90d\ub2c8\ub2e4.<\/p>\n<p>\uc774\ub807\uac8c <code>PostsRepository<\/code> \ub3c4 \uc790\ub3d9\uc0dd\uc131\ub418\uace0, <code>PostsService<\/code> \ub3c4 \uc790\ub3d9\uc0dd\uc131\ub429\ub2c8\ub2e4.<\/p>\n<p><code>postsRepository.save()<\/code>, <code>posts.update()<\/code> \ub294 \ucca8\ubcf4\ub294\ub370 \uc774\uac74 \ubaa8\ub0d0?<\/p>\n<p><code>PostsRepository<\/code> \uac00 \uc0c1\uc18d\ud558\ub294 <code>JpaRepository<\/code> \uc5d0 \uc774\ubbf8 \uad6c\ud604(?)\ub418\uc5b4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc2e4\ud589\uc774 \uac00\ub2a5\ud574 \uc9d1\ub2c8\ub2e4. \ubb50&#8230; \uc815\ud655\ud788\ub294 \uc815\uc758\ub9cc \ub418\uc5b4 \uc788\uc9c0 \uad6c\ud604\ub41c\uac74 \uc544\ub2cc\ub370&#8230; \ub108\ubb34 \uae4a\uac8c \ub4e4\uc5b4\uac00\uba74 \ud798\ub4e4\uc5b4\uc9c0\ubbc0\ub85c \ub118\uc5b4\uac11\uc2dc\ub2e4.(\uc815 \uad81\uae08\ud558\uc2dc\uba74 JpaRepository \ub97c \uc18c\uc2a4\ubcf4\uae30 \ud558\uc2dc\uba74 \ub429\ub2c8\ub2e4.)<\/p>\n<h2>web \ub808\uc774\uc5b4<\/h2>\n<p>RestController \ub294 json \uc744 \ubc18\ud658\ud558\ub294 \ucee8\ud2b8\ub864\ub7ec\uc774\uace0, Controller \ub294 html \uc744 \ubc18\ud658\ud558\ub294 \ucee8\ud2b8\ub864\ub7ec\uc785\ub2c8\ub2e4.<\/p>\n<h3>RestController \uc0dd\uc131<\/h3>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/PostsApiController.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web;\n\nimport kr.co.episode.example.service.posts.PostsService;\nimport kr.co.episode.example.web.dto.PostsResponseDto;\nimport kr.co.episode.example.web.dto.PostsSaveRequestDto;\nimport kr.co.episode.example.web.dto.PostsUpdateRequestDto;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.web.bind.annotation.*;\n\n@RequiredArgsConstructor\n@RestController\npublic class PostsApiController {\n\n    private final PostsService postsService;\n\n    @PostMapping(&quot;\/api\/v1\/posts&quot;)\n    public Long save(@RequestBody PostsSaveRequestDto postsSaveRequestDto) {\n        return postsService.save(postsSaveRequestDto);\n    }\n\n    @PutMapping(&quot;\/api\/v1\/posts\/{id}&quot;)\n    public Long update(@PathVariable Long id, @RequestBody PostsUpdateRequestDto postsUpdateRequestDto) {\n        return postsService.update(id, postsUpdateRequestDto);\n    }\n\n    @GetMapping(&quot;\/api\/v1\/posts\/{id}&quot;)\n    public PostsResponseDto findById(@PathVariable Long id) {\n        return postsService.findById(id);\n    }\n\n    @DeleteMapping(&quot;\/api\/v1\/posts\/{id}&quot;)\n    public Long delete(@PathVariable Long id) {\n        postsService.delete(id);\n        return id;\n    }\n}<\/code><\/pre>\n<p><code>@PathVariable<\/code> \uc744 \uc774\uc6a9\ud574 url \uc5d0\uc11c \ud30c\ub77c\ubbf8\ud130\ub97c \ucd94\ucd9c\ud574 \uc804\ub2ec\ubc1b\ub294 \ubc29\ubc95\ub3c4 \ubcf4\uc5ec\uc9d1\ub2c8\ub2e4.<\/p>\n<h3>Controller \uc0dd\uc131<\/h3>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/IndexController.java<\/p>\n<pre><code class=\"language-java\">package kr.co.episode.example.web;\n\nimport kr.co.episode.example.service.posts.PostsService;\nimport kr.co.episode.example.web.dto.PostsResponseDto;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\n\n@RequiredArgsConstructor\n@Controller\npublic class IndexController {\n\n    private final PostsService postsService;\n\n    @GetMapping(&quot;\/&quot;)\n    public String index(Model model) {\n        model.addAttribute(&quot;posts&quot;, postsService.findAllDesc());\n        return &quot;index&quot;;\n    }\n\n    @GetMapping(&quot;\/posts\/save&quot;)\n    public String postsSave() {\n        return &quot;posts-save&quot;;\n    }\n\n    @GetMapping(&quot;\/posts\/update\/{id}&quot;)\n    public String postsUpdate(@PathVariable Long id, Model model) {\n        PostsResponseDto dto = postsService.findById(id);\n        model.addAttribute(&quot;post&quot;, dto);\n\n        return &quot;posts-update&quot;;\n    }\n}<\/code><\/pre>\n<p><code>public String index(Model model)<\/code> \uc5d0\uc11c Model \ud30c\ub77c\ubbf8\ud130\ub97c \uc804\ub2ec\ubc1b\uc2b5\ub2c8\ub2e4. \uc774 \ud30c\ub77c\ubbf8\ud130\uc5d0 index.html \ud15c\ud50c\ub9bf\uc5d0 \uc804\ub2ec\ud560 \ub370\uc774\ud0c0\ub97c \uc124\uc815\ud558\uac8c \ub429\ub2c8\ub2e4.<\/p>\n<h3>html, js \uc0dd\uc131<\/h3>\n<p>src\/main\/resources\/static\/js\/app\/index.js<\/p>\n<pre><code class=\"language-javascript\">var main = {\n    init : function() {\n        var _this = this;\n        $(&#039;#btn-save&#039;).on(&#039;click&#039;, function() {\n            _this.save();\n        });\n        $(&#039;#btn-update&#039;).on(&#039;click&#039;, function() {\n            _this.update();\n        });\n        $(&#039;#btn-delete&#039;).on(&#039;click&#039;, function() {\n            _this.delete();\n        });\n        $(&#039;#btn-search&#039;).on(&#039;click&#039;, function() {\n            document.frm.submit();\n        });\n    },\n    save : function() {\n        var data = {\n            title : $(&#039;#title&#039;).val(),\n            author : $(&#039;#author&#039;).val(),\n            content : $(&#039;#content&#039;).val()\n        }\n\n        $.ajax({\n            type : &#039;POST&#039;,\n            url : &#039;\/api\/v1\/posts&#039;,\n            dataType : &#039;json&#039;,\n            contentType : &#039;application\/json; charset=utf-8&#039;,\n            data : JSON.stringify(data)\n        }).done(function() {\n            alert(&#039;\uae00\uc774 \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4.&#039;);\n            window.location.href = &#039;\/&#039;;\n        }).fail(function(error) {\n            \/\/alert(JSON.stringify(error));\n            if (error.status == 403) {\n                alert(&#039;\uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.&#039;);\n            } else {\n                alert(&#039;\uc54c \uc218 \uc5c6\ub294 \uc624\ub958\uc785\ub2c8\ub2e4.&#039; + error.status);\n            }\n        });\n    },\n    update : function() {\n        var id = $(&#039;#id&#039;).val();\n        var data = {\n            title : $(&#039;#title&#039;).val(),\n            content : $(&#039;#content&#039;).val()\n        }\n\n        $.ajax({\n            type : &#039;PUT&#039;,\n            url : &#039;\/api\/v1\/posts\/&#039; + id,\n            dataType : &#039;json&#039;,\n            contentType : &#039;application\/json; charset=utf-8&#039;,\n            data : JSON.stringify(data)\n        }).done(function() {\n            alert(&#039;\uae00\uc774 \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.&#039;);\n            window.location.href = &#039;\/&#039;;\n        }).fail(function(error) {\n            alert(JSON.stringify(error));\n        });\n    },\n    delete : function() {\n        var id = $(&#039;#id&#039;).val();\n\n        $.ajax({\n            type : &#039;DELETE&#039;,\n            url : &#039;\/api\/v1\/posts\/&#039; + id,\n            dataType : &#039;json&#039;,\n            contentType : &#039;application\/json; charset=utf-8&#039;\n        }).done(function() {\n            alert(&#039;\uae00\uc774 \uc0ad\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4.&#039;);\n            window.location.href = &#039;\/&#039;;\n        }).fail(function(error) {\n            alert(JSON.stringify(error));\n        });\n    }\n};\n\nmain.init();<\/code><\/pre>\n<p>IndexController \uc5d0\uc11c \uc785\ub825\ud55c <code>posts<\/code> \uc18d\uc131\uc774 \uc544\ub798 \ud15c\ud50c\ub9bf html \uc5d0\uc11c \uc0ac\uc6a9\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>src\/main\/resources\/templates\/index.html<\/p>\n<pre><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html xmlns:th=&quot;http:\/\/www.thymeleaf.org&quot;&gt;\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;title&gt;\uac8c\uc2dc\ud310&lt;\/title&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.2\/css\/bootstrap.min.css&quot;&gt;\n    &lt;style&gt;\n        .container p { display: inline }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body class=&quot;container&quot;&gt;\n\n&lt;h1&gt;\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \uac8c\uc2dc\ud310&lt;\/h1&gt;\n\n&lt;div class=&quot;col-md-12&quot;&gt;\n    &lt;div class=&quot;row&quot;&gt;\n        &lt;div class=&quot;col-md-6&quot;&gt;\n            &lt;a href=&quot;\/posts\/save&quot; role=&quot;button&quot; class=&quot;btn&quot; btn-primary&gt;\uae00 \ub4f1\ub85d&lt;\/a&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;div style=&quot;height: 80px;&quot;&gt;\n\n&lt;\/div&gt;\n\n&lt;table class=&quot;table&quot;&gt;\n    &lt;tr&gt;\n        &lt;th&gt;\uae00 \ubc88\ud638&lt;\/th&gt;\n        &lt;th&gt;\uae00\uc4f4\uc774&lt;\/th&gt;\n        &lt;th&gt;\uae00 \uc81c\ubaa9&lt;\/th&gt;\n        &lt;th&gt;\ucd5c\uc885\uc218\uc815&lt;\/th&gt;\n    &lt;\/tr&gt;\n    &lt;tr th:each=&quot;posts: ${posts}&quot;&gt;\n        &lt;td th:text=&quot;${posts.id}&quot;&gt;&lt;\/td&gt;\n        &lt;td&gt;\n            &lt;a th:href=&quot;${posts.link}&quot; th:text=&quot;${posts.author}&quot; \/&gt;\n        &lt;\/td&gt;\n        &lt;td&gt;\n            &lt;a th:href=&quot;${posts.link}&quot; th:text=&quot;${posts.title}&quot; \/&gt;\n        &lt;\/td&gt;\n        &lt;td th:text=&quot;${posts.modifiedDate}&quot;&gt;&lt;\/td&gt;\n    &lt;\/tr&gt;\n&lt;\/table&gt;\n\n&lt;script src=&quot;https:\/\/code.jquery.com\/jquery-3.3.1.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script src=&quot;https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.3.1\/js\/bootstrap.min.js&quot;&gt;&lt;\/script&gt;\n\n&lt;script src=&quot;\/js\/app\/index.js&quot;&gt;&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p>src\/main\/resources\/templates\/posts-save.html<\/p>\n<pre><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html xmlns:th=&quot;http:\/\/www.thymeleaf.org&quot;&gt;\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;title&gt;\uac8c\uc2dc\ud310&lt;\/title&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.2\/css\/bootstrap.min.css&quot;&gt;\n    &lt;style&gt;\n        .container p { display: inline }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body class=&quot;container&quot;&gt;\n\n&lt;h1&gt;\uac8c\uc2dc\uae00 \ub4f1\ub85d&lt;\/h1&gt;\n\n&lt;div class=&quot;col-md-12&quot;&gt;\n    &lt;div class=&quot;col-md-4&quot;&gt;\n        &lt;form&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;title&quot;&gt;\uc81c\ubaa9&lt;\/label&gt;\n                &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;title&quot; placeholder=&quot;\uc81c\ubaa9\uc744 \uc785\ub825\ud558\uc138\uc694.&quot; \/&gt;\n            &lt;\/div&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;author&quot;&gt;\uc791\uc131\uc790&lt;\/label&gt;\n                &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;author&quot; placeholder=&quot;\uc791\uc131\uc790\ub97c \uc785\ub825\ud558\uc138\uc694.&quot; \/&gt;\n            &lt;\/div&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;content&quot;&gt;\ub0b4\uc6a9&lt;\/label&gt;\n                &lt;textarea class=&quot;form-control&quot; id=&quot;content&quot; placeholder=&quot;\ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc138\uc694.&quot;&gt;&lt;\/textarea&gt;\n            &lt;\/div&gt;\n        &lt;\/form&gt;\n\n        &lt;button type=&quot;button&quot; class=&quot;btn btn-primary&quot; id=&quot;btn-save&quot;&gt;\ub4f1\ub85d&lt;\/button&gt;\n        &lt;a href=&quot;\/&quot; role=&quot;button&quot; class=&quot;btn btn-secondary&quot;&gt;\ucde8\uc18c&lt;\/a&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;script src=&quot;https:\/\/code.jquery.com\/jquery-3.3.1.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script src=&quot;https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.3.1\/js\/bootstrap.min.js&quot;&gt;&lt;\/script&gt;\n\n&lt;script src=&quot;\/js\/app\/index.js&quot;&gt;&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p>\uc5ed\uc2dc, IndexController \uc5d0\uc11c \uc785\ub825\ubc1b\uc740 <code>post<\/code> \uc18d\uc131\uc774 \uc0ac\uc6a9\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>src\/main\/resources\/templates\/posts-update.html<\/p>\n<pre><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html xmlns:th=&quot;http:\/\/www.thymeleaf.org&quot;&gt;\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;title&gt;\uac8c\uc2dc\ud310&lt;\/title&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.2\/css\/bootstrap.min.css&quot;&gt;\n    &lt;style&gt;\n        .container p { display: inline }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body class=&quot;container&quot;&gt;\n\n&lt;h1&gt;\uac8c\uc2dc\ubb3c \uc218\uc815&lt;\/h1&gt;\n\n&lt;div class=&quot;col-md-12&quot;&gt;\n    &lt;div class=&quot;col-md-4&quot;&gt;\n        &lt;form&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;id&quot;&gt;\uae00\ubc88\ud638&lt;\/label&gt;\n                &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;id&quot; name=&quot;id&quot; th:value=&quot;${post.id}&quot; readonly \/&gt;\n            &lt;\/div&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;title&quot;&gt;\uc81c\ubaa9&lt;\/label&gt;\n                &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;title&quot; name=&quot;title&quot; th:value=&quot;${post.title}&quot; \/&gt;\n            &lt;\/div&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;author&quot;&gt;\uc791\uc131\uc790&lt;\/label&gt;\n                &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;author&quot; name=&quot;author&quot; th:value=&quot;${post.author}&quot; readonly \/&gt;\n            &lt;\/div&gt;\n            &lt;div class=&quot;form-group&quot;&gt;\n                &lt;label for=&quot;content&quot;&gt;\ub0b4\uc6a9&lt;\/label&gt;\n                &lt;textarea class=&quot;form-control&quot; id=&quot;content&quot; name=&quot;content&quot; th:text=&quot;${post.content}&quot;&gt;&lt;\/textarea&gt;\n            &lt;\/div&gt;\n        &lt;\/form&gt;\n\n        &lt;button type=&quot;button&quot; class=&quot;btn btn-primary&quot; id=&quot;btn-update&quot;&gt;\uc218\uc815&lt;\/button&gt;\n        &lt;a href=&quot;\/&quot; role=&quot;button&quot; class=&quot;btn btn-secondary&quot;&gt;\ucde8\uc18c&lt;\/a&gt;\n        &lt;button type=&quot;button&quot; class=&quot;btn btn-danger&quot; id=&quot;btn-delete&quot;&gt;\uc0ad\uc81c&lt;\/button&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;script src=&quot;https:\/\/code.jquery.com\/jquery-3.3.1.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script src=&quot;https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.3.1\/js\/bootstrap.min.js&quot;&gt;&lt;\/script&gt;\n\n&lt;script src=&quot;\/js\/app\/index.js&quot;&gt;&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\uac8c\uc2dc\ubb3c\uc744 \uc785\ub825\/\uc218\uc815\/\uc0ad\uc81c\/\ub9ac\uc2a4\ud2b8\ud45c\uc2dc \ud558\ub294 \uac8c\uc2dc\ud310\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. \uac80\uc0c9\uae30\ub2a5\uc774\ub098 \ud398\uc774\uc9d5 \uae30\ub2a5\uc740 \ub2e4\uc74c \uae00\uc5d0\uc11c \ucd94\uac00\ud558\uae30\uc5d0 \uc5ec\uae30\uc11c\ub294 \uc81c\uc678\ub429\ub2c8\ub2e4.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-80","post","type-post","status-publish","format-standard","hentry","category-spring-boot-2-1"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/80","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=80"}],"version-history":[{"count":26,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":1436,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions\/1436"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}