๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“• Spring Framework/Spring Project

[๋ฆฌํŒฉํ† ๋ง] ๋„๋ฉ”์ธ ๋ชจ๋ธ ์ค‘์‹ฌ Clean Architecture ๋กœ์˜ ๋ฆฌํŒฉํ† ๋ง

by GroovyArea 2022. 12. 12.

ํ”„๋กœ์ ํŠธ๋ฅผ ์ˆ˜๋„ ์—†์ด ๋ฆฌํŒฉํ† ๋งํ–ˆ๋‹ค.
๋ณด๋‹ค ๋” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ,
์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ,
๋” ์ž‘์€ ๊ฐ์ฒด๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ๊ณ„์†ํ•ด์„œ ๊ณ ๋ฏผํ•˜๊ณ  ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

์ง€๋‚œ ๋‹ฌ๋ถ€ํ„ฐ ํ•ด์„œ ์†Œํ”„ํŠธ ์›จ์–ด ์•„ํ‚คํ…์ฒ˜์— ๊ด€ํ•ด์„œ ๊ด€์‹ฌ์ด ์ƒ๊ฒผ๋‹ค.
ํด๋ฆฐ ์ฝ”๋“œ๋ฅผ ์ถ”๊ตฌํ•˜๋‹ค ๋ณด๋‹ˆ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์„ค๊ณ„์  ๊ณ ๋ฏผ์œผ๋กœ ๊ท€๊ฒฐ๋˜์—ˆ๋‹ค.

์›ํ‹ฐ๋“œ ๋ฐฑ์—”๋“œ ์ฑŒ๋ฆฐ์ง€๋ฅผ ํ•˜๋ฉฐ ์•Œ๊ฒŒ๋œ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜,
๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„ ์ฒ ์ € ์ž…๋ฌธ,
๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค๋ฅผ ์ฝ์–ด๊ฐ€๋ฉฐ,
๋‚ด๊ฐ€ ๊ตฌ์„ฑํ•ด์˜ค๋˜ ์†Œํ”„ํŠธ์›จ์–ด ์„ค๊ณ„์˜ ํฐ ์ „ํ™˜์ ์„ ๋งž์ดํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๋‹จ์ˆœํžˆ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋งŒ์„ ๋งŒ๋“œ๋Š”๊ฒŒ ์•„๋‹Œ ๋ณธ ํ”„๋กœ์ ํŠธ์— ์ด๋ฅผ ์ ์šฉ์‹œ์ผœ๋ณด๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.
MSA ๋Š” ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง์ด๋ผ ํŒ๋‹จํ–ˆ๊ณ , ๋ชจ๋…ธ๋ฆฌ์Šค ๊ตฌ์กฐ์ด์ง€๋งŒ ์ตœ๋Œ€ํ•œ ๋„๋ฉ”์ธ ๋ณ„ ๋ถ„๋ฆฌ๊ฐ€ ๋œ ์ƒ์œ„ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ๋กœ ๋‚˜๋ˆ„์–ด ๋ฆฌํŒฉํ† ๋งํ–ˆ๋‹ค.
๊ธฐ์กด ์ฝ”๋“œ ๊ตฌ์„ฑ

๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ๋ฅผ ๋‚˜๋ˆ„๊ธฐ

๊ธฐ์กด ๊ตฌ์กฐ์—๋Š” domain ์ด๋ž€ ์ตœ์ƒ์œ„ ๊ตฌ์กฐ ์•„๋ž˜ ๋„๋ฉ”์ธ ์ปจํ…์Šค๋“ค์ด ์กด์žฌํ•จ.
์ด๋ฅผ ๋ฐ”๊นฅ์œผ๋กœ ๋นผ์„œ ํ•˜๋‚˜์˜ ๋„๋ฉ”์ธ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

  • global ํŒจํ‚ค์ง€๋Š” ๊ฐ ์ปจํ…์ŠคํŠธ๊ฐ„ ์ „์—ญ์  ๊ณต์œ 
  • ๋‚˜๋จธ์ง€ ํŒจํ‚ค์ง€๋Š” ๋„๋ฉ”์ธ ์ค‘์‹ฌ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ๋กœ ์„ค๊ณ„

 

์ฐจ์ƒ์œ„ ๊ตฌ์กฐ - User

  • user ํŒจํ‚ค์ง€
  • ์–ด๋Œ‘ํ„ฐ in out ๊ตฌ์„ฑ
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - usecase์™€ ๊ตฌํ˜„์ฒด port service ๊ตฌ์„ฑ
  • ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ๋Š” jpa ์—”ํ‹ฐํ‹ฐ๋กœ ๊ตฌ์„ฑ
  • dto ๋ชจ๋ธ์€ ์ „์—ญ์ ์ด๋ฏ€๋กœ ๊ฐ ๊ณ„์ธต ๊ฐ„ ๊ณต์œ 

 

์„ธ๋ถ€ ๊ตฌ์กฐ - User

  • ๋Œ€๋žต์  ์„ธ๋ถ€ ๊ตฌ์กฐ ์˜ˆ์‹œ

 

๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ ๋ชจ๋ธ - User

@Table(name = "users")
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class User extends BaseTimeEntity<User> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String loginId;

    private String password;

    private String salt;

    private String name;

    @Column(unique = true)
    private String email;

    private String address;

    private String zipcode;

    @Enumerated(EnumType.STRING)
    private Role role;

    // <๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฉ”์„œ๋“œ> //

    public void updateUserInfo(final User modifiableEntity, final String updatePassword) {
        this.name = modifiableEntity.getName();
        this.email = modifiableEntity.getEmail();
        this.address = modifiableEntity.getAddress();
        this.zipcode = modifiableEntity.getZipcode();
        this.password = updatePassword;
    }

    public void remove() {
        this.role = Role.ROLE_WITHDRAWAL;
        this.delete();
    }

}
  • Jpa entitiy๋กœ ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ ๋ชจ๋ธ์„ ์‚ฌ์šฉ
  • ๊ธฐ์กด ์—ฐ๊ด€ ๊ด€๊ณ„ ์‚ญ์ œ (order์™€ ์—ฐ๊ด€ ๊ด€๊ณ„ ์˜€๋‹ค.)


์ด๋ ‡๊ฒŒ User domain bounded context๋ฅผ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณด์•˜๋‹ค.

๊ณ ๋ฏผํ•ด ๋ณผ ๋ถ€๋ถ„

  • ๋„๋ฉ”์ธ์ด ๋ถ„๋ฆฌ ๋˜์–ด ์žˆ์–ด๋„ ํŠธ๋žœ์žญ์…˜์„ ์—ฐ๊ฒฐ ์ง€์–ด์•ผ ํ•œ๋‹ค.

 

์ฒซ๋ฒˆ ์งธ ๋ฐฉ์•ˆ

  • Kafka ์™€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง์ด๋ผ ํŒ๋‹จ.
  • Spring์ด ์ œ๊ณตํ•˜๋Š” ๋™๊ธฐ ํ˜ธ์ถœ ํด๋ผ์ด์–ธํŠธ Feign์„ ์‚ฌ์šฉ
  • MSA ๋กœ ์ „ํ™˜ํ•  ๊ฒฝ์šฐ ์ข‹์€ ์„ ํƒ์ง€๊ฐ€ ๋  ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ์—ˆ๋‹ค.

๋‘๋ฒˆ ์งธ ๋ฐฉ์•ˆ

  • Application Event Publisher๋ฅผ ์‚ฌ์šฉ
  • ๋ชจ๋…ธ๋ฆฌ์Šค ๊ตฌ์„ฑ์—์„œ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ ๊ฐ„๋‹จํžˆ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ผ ํŒ๋‹จํ–ˆ๋‹ค.

 

๋‚˜๋Š” ํ›„์ž๋ฅผ ํƒํ–ˆ๋‹ค.
Feign ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์กฐ์ฐจ ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค.
๋ฌด์—‡๋ณด๋‹ค MSA๋กœ ์ „ํ™˜ํ•  ์ƒ๊ฐ์ด ์—†์—ˆ๊ธฐ์—, ๊ตณ์ด API ๋™๊ธฐ ํ˜ธ์ถœ์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

Application Event

๋‹ค๋ฅธ ๋„๋ฉ”์ธ ์ปจํ…์ŠคํŠธ์ด์ง€๋งŒ ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‹จ์œ„๋กœ ๋ฌถ์—ฌ์•ผ ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค
์ด ๊ฒƒ์„ ๋™๊ธฐ ์ด๋ฒคํŠธ๋กœ ํ•ด๊ฒฐํ•จ.

eventPublisher.publishEvent(
        eventBuilder.createEvent(new OrderVariation(
                savedPayment.getOrderId(),
                paymentId,
                false))
);

eventPublisher.publishEvent(
        eventBuilder.createEvent(ItemsVariation.builder()
                .numbers(itemNumbers.stream().map(Long::valueOf).toList())
                .quantities(itemQuantities.stream().map(Integer::valueOf).toList())
                .totalAmount(response.getAmount().getTotal())
                .status(false)
                .build())
);
  • ๊ฒฐ์ œ ์ทจ์†Œ๋ฅผ ํ–ˆ์„ ๊ฒฝ์šฐ์ด๋‹ค.
  • Order ๋„๋ฉ”์ธ, Product ๋„๋ฉ”์ธ์€ ๋ณ„๋„์˜ ์ปจํ…์ŠคํŠธ์ด๋‹ค.
  • ์ฃผ๋ฌธ ์ƒํƒœ ๋ณ€๊ฒฝ๊ณผ ์ƒํ’ˆ ์ˆ˜๋Ÿ‰ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ–ˆ๋‹ค.
  • ๋‹น์—ฐํžˆ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” @Transactional์„ ๋ถ™์—ฌ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๊ฐ์‹ธ์ง„๋‹ค.

  • event ๋Š” ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋Š” ๊ตฌ์„ฑ์ด๋ฏ€๋กœ out ํŒจํ‚ค์ง€์— ์œ„์น˜

 

  • order ๋„๋ฉ”์ธ์—์„œ ์ด๋ฒคํŠธ ๊ตฌ๋…์ž๋Š” ๋ฐ–์—์„œ ์•ˆ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๊ตฌ์„ฑ์œผ๋กœ in ์— ์œ„์น˜

 

@EventListener
public void doOrderEvent(EventModel eventModel) {
    String eventAction = eventModel.getEventAction()
            .orElseThrow(EventNotExistsException::new);

    if (eventAction.equals(ORDER_EVENT)) {
        String payload = eventModel.getPayload();

        .....

=> ์ด๋Ÿฐ ์‹์œผ๋กœ ๋™๊ธฐ๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ฝ์–ด ์‹คํ–‰
=> ๋™๊ธฐ ์‹คํ–‰

@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "payment_id")
private Long paymentId;
  • Order ์—”ํ‹ฐํ‹ฐ ๋ชจ๋ธ
  • ๊ธฐ์กด ์—ฐ๊ด€๊ด€๊ณ„๋Š” ์ง์ ‘ jpa entity ๋งคํ•‘
  • ์ง€๊ธˆ์€ pk๋งŒ ์ปฌ๋Ÿผ์œผ๋กœ ๊ฐ€์ง€๋Š” ๊ตฌ์„ฑ
  • ์ด pk๋ฅผ ๊ฐ€์ง€๊ณ  ๋‹ค๋ฅธ ๋„๋ฉ”์ธ ์ปจํ…์ŠคํŠธ์˜ api ์š”์ฒญ ๊ฐ€๋Šฅ

 

์ด๋Ÿฐ์‹์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง์„ ํ•ด๋ณด์•˜๋‹ค.
๋‚˜์ค‘์— MSA๋ฅผ ์„ค๊ณ„ํ•  ๊ตฌ์„ฑ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๊ฒฝ์šฐ
๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋‚˜ ํŠธ๋žœ์žญ์…˜ ๋‹จ์œ„๋ฅผ ์ง€ํ‚ค๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ํŒจํ„ด๋“ค์„ ์ ์šฉํ•  ์ดˆ์„์„ ๋งˆ๋ จํ•œ ๊ฒƒ ๊ฐ™๋‹ค.
์–ด๋А์ •๋„ ๊ฐ์„ ์žก์•˜๋‹ค๋Š” ๋ง์ด๋‹ค!

์ด๋ ‡๊ฒŒ ์žก์•„๋‚˜๊ฐ€๋ฉด ๊ทธ ๋งŒํผ ๋‚ด ์‹ค๋ ฅ์ด ๋œ๋‹ค๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค.



๋ฐ˜์‘ํ˜•